fixed: LINUX build errors
[xbmc:xbmc.git] / xbmc / lib / UnrarXLib / extract.cpp
1 #include "rar.hpp"
2 #include "Util.h"
3 #ifdef _LINUX
4 #include "XSyncUtils.h"
5 #include "XEventUtils.h"
6 #endif
7
8 CmdExtract::CmdExtract()
9 {
10   TotalFileCount=0;
11   *Password=0;
12   Unp = NULL;
13 }
14
15
16 CmdExtract::~CmdExtract()
17 {
18   delete Unp;
19   memset(Password,0,sizeof(Password));
20 }
21
22
23 void CmdExtract::DoExtract(CommandData *Cmd)
24 {
25   if (!Unp)
26   {
27       Unp=new Unpack(&DataIO);
28       Unp->Init(NULL);
29   }
30   DataIO.SetCurrentCommand(*Cmd->Command);
31
32   struct FindData FD;
33   while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
34     if (FindFile::FastFind(ArcName,ArcNameW,&FD))
35       DataIO.TotalArcSize+=FD.Size;
36   Cmd->ArcNames->Rewind();
37   while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
38   {
39     while (ExtractArchive(Cmd)==EXTRACT_ARC_REPEAT)
40       ;
41     if (FindFile::FastFind(ArcName,ArcNameW,&FD))
42       DataIO.ProcessedArcSize+=FD.Size;
43   }
44
45   if (TotalFileCount==0 && *Cmd->Command!='I')
46   {
47     if (!PasswordCancelled)
48     {
49       mprintf(St(MExtrNoFiles));
50     }
51     ErrHandler.SetErrorCode(WARNING);
52   }
53 #ifndef GUI
54   else if (!Cmd->DisableDone)
55   {
56     if (*Cmd->Command=='I')
57     {
58       mprintf(St(MDone));
59     }
60     else
61     {
62       if (ErrHandler.GetErrorCount()==0)
63       {
64         mprintf(St(MExtrAllOk));
65       }
66       else
67       {
68         mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount());
69       }
70     }
71   }
72 #endif
73 }
74
75
76 void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
77 {
78   if (!Unp)
79   {
80       Unp=new Unpack(&DataIO);
81       Unp->Init(NULL);
82   }
83
84   DataIO.UnpArcSize=Arc.FileLength();
85
86   FileCount=0;
87   MatchedArgs=0;
88 #ifndef SFX_MODULE
89   FirstFile=true;
90 #endif
91
92   if (*Cmd->Password!=0)
93     strcpy(Password,Cmd->Password);
94   PasswordAll=(*Cmd->Password!=0);
95
96   DataIO.UnpVolume=false;
97
98   PrevExtracted=false;
99   SignatureFound=false;
100   AllMatchesExact=true;
101   ReconstructDone=false;
102 }
103
104
105 EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
106 {
107   Archive Arc(Cmd);
108   if (!Arc.WOpen(ArcName,ArcNameW))
109   {
110     ErrHandler.SetErrorCode(OPEN_ERROR);
111     return(EXTRACT_ARC_NEXT);
112   }
113
114   if (!Arc.IsArchive(true))
115   {
116 #ifndef GUI
117     mprintf(St(MNotRAR),ArcName);
118 #endif
119     if (CmpExt(ArcName,"rar"))
120       ErrHandler.SetErrorCode(WARNING);
121     return(EXTRACT_ARC_NEXT);
122   }
123
124   if (!Arc.IsOpened())
125     return(EXTRACT_ARC_NEXT);
126
127 #ifndef SFX_MODULE
128   if (Arc.Volume && Arc.NotFirstVolume)
129   {
130     char FirstVolName[NM];
131
132     VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
133     if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
134         Cmd->ArcNames->Search(FirstVolName,NULL,false))
135       return(EXTRACT_ARC_NEXT);
136   }
137 #endif
138   ExtractArchiveInit(Cmd,Arc);
139
140   if (*Cmd->Command=='T' || *Cmd->Command=='I')
141     Cmd->Test=true;
142
143 #ifndef GUI
144   if (*Cmd->Command=='I')
145     Cmd->DisablePercentage=true;
146   else
147     if (Cmd->Test)
148     {
149       mprintf(St(MExtrTest),ArcName);
150     }
151     else
152     {
153       mprintf(St(MExtracting),ArcName);
154     }
155 #endif
156
157   Arc.ViewComment();
158
159   while (1)
160   {
161     int Size=Arc.ReadHeader();
162     bool Repeat=false;
163     if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
164     {
165       if (Repeat)
166       {
167         return(EXTRACT_ARC_REPEAT);
168       }
169       else
170         break;
171     }
172   }
173   return(EXTRACT_ARC_NEXT);
174 }
175
176
177 bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,bool &Repeat)
178 {
179   if (!Unp)
180   {
181     Unp=new Unpack(&DataIO);
182     Unp->Init(NULL);
183   }
184   char Command=*Cmd->Command;
185
186   if (HeaderSize<=0)
187   {
188     if (DataIO.UnpVolume)
189     {
190 //#ifdef NOVOLUME
191 //      return(false);
192 //#else
193       if (!MergeArchive(Arc,NULL,false,Command))
194       {
195         ErrHandler.SetErrorCode(WARNING);
196         return(false);
197       }
198       SignatureFound=false;
199 //#endif
200     }
201     else
202       return(false);
203   }
204   int HeadType=Arc.GetHeaderType();
205   if (HeadType!=FILE_HEAD)
206   {
207     if (HeadType==AV_HEAD || HeadType==SIGN_HEAD)
208       SignatureFound=true;
209 #if !defined(SFX_MODULE) && !defined(_WIN_CE)
210     if (HeadType==SUB_HEAD && PrevExtracted)
211       SetExtraInfo(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);    
212 #endif
213     if (HeadType==NEWSUB_HEAD)
214     {
215       if (Arc.SubHead.CmpName(SUBHEAD_TYPE_AV))
216         SignatureFound=true;
217 #if !defined(NOSUBBLOCKS) && !defined(_WIN_CE)
218       if (PrevExtracted)
219         SetExtraInfoNew(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);
220 #endif
221     }
222     if (HeadType==ENDARC_HEAD)
223     {
224       if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)
225       {
226 #ifndef NOVOLUME
227         if (!MergeArchive(Arc,NULL,false,Command))
228         {
229           ErrHandler.SetErrorCode(WARNING);
230           return(false);
231         }
232         SignatureFound=false;
233 #endif
234         Arc.Seek(Arc.CurBlockPos,SEEK_SET);
235         return(true);
236       }
237       else
238         return(false);
239     }
240     Arc.SeekToNext();
241     return(true);
242   }
243   PrevExtracted=false;
244
245   if (SignatureFound ||
246      (!Cmd->Recurse && MatchedArgs>=(int)Cmd->FileArgs->ItemsCount() && AllMatchesExact))
247     return(false);
248
249   // char ArcFileName[NM];
250   CSmartStr ArcFileName(NM);
251
252   IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
253   strcpy(ArcFileName,Arc.NewLhd.FileName);
254
255   // wchar ArcFileNameW[NM];
256   CSmartStrW ArcFileNameW(NM);
257   *ArcFileNameW=0;
258
259   int MatchType=MATCH_WILDSUBPATH;
260   
261   bool EqualNames=false;
262   int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames,MatchType);
263   bool ExactMatch=MatchNumber!=0;
264 #if !defined(SFX_MODULE) && !defined(_WIN_CE)
265   if (Cmd->ExclPath==EXCL_BASEPATH)
266   {
267     *Cmd->ArcPath=0;
268     if (ExactMatch)
269     {
270       Cmd->FileArgs->Rewind();
271       if (Cmd->FileArgs->GetString(Cmd->ArcPath,NULL,sizeof(Cmd->ArcPath),MatchNumber-1))
272         *PointToName(Cmd->ArcPath)=0;
273     }
274   }
275 #endif
276   if (ExactMatch && !EqualNames)
277     AllMatchesExact=false;
278
279 #ifdef UNICODE_SUPPORTED
280   bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
281 #else
282   bool WideName=false;
283 #endif
284
285 #ifdef _APPLE
286   if (WideName)
287   {
288     WideToUtf(Arc.NewLhd.FileNameW,ArcFileName,sizeof(ArcFileName));
289     WideName=false;
290   }
291 #endif
292
293   wchar *DestNameW=WideName ? DestFileNameW:NULL;
294
295 #ifdef UNICODE_SUPPORTED
296   if (WideName)
297   {
298     ConvertPath(Arc.NewLhd.FileNameW,ArcFileNameW);
299     // char Name[NM];
300     CSmartStr Name(NM);
301     WideToChar(ArcFileNameW,Name);
302     if (IsNameUsable(Name))
303     strcpy(ArcFileName,Name);
304   }
305 #endif
306
307   ConvertPath(ArcFileName,ArcFileName);
308
309   if (Arc.IsArcLabel())
310     return(true);
311
312   if (Arc.NewLhd.Flags & LHD_VERSION)
313   {
314     if (Cmd->VersionControl!=1 && !EqualNames)
315     {
316       if (Cmd->VersionControl==0)
317         ExactMatch=false;
318       int Version=ParseVersionFileName(ArcFileName,ArcFileNameW,false);
319       if (Cmd->VersionControl-1==Version)
320         ParseVersionFileName(ArcFileName,ArcFileNameW,true);
321       else
322         ExactMatch=false;
323     }
324   }
325   else
326     if (!Arc.IsArcDir() && Cmd->VersionControl>1)
327       ExactMatch=false;
328
329   Arc.ConvertAttributes();
330
331 #ifndef SFX_MODULE
332   if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
333   {
334     // char CurVolName[NM];
335     CSmartStr CurVolName(NM);
336     strcpy(CurVolName,ArcName);
337
338     VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING) != 0);
339     if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
340     {
341       *ArcNameW=0;
342       Repeat=true;
343       return(false);
344     }
345 #if !defined(RARDLL) && !defined(_WIN_CE)
346     if (!ReconstructDone)
347     {
348       ReconstructDone=true;
349
350       RecVolumes RecVol;
351       if (RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true))
352       {
353         Repeat=true;
354         return(false);
355       }
356     }
357 #endif
358     strcpy(ArcName,CurVolName);
359   }
360 #endif
361
362   DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER);
363   DataIO.NextVolumeMissing=false;
364
365   Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
366
367   bool TestMode=false;
368   bool ExtrFile=false;
369   bool SkipSolid=false;
370
371 #ifndef SFX_MODULE
372   if (FirstFile && (ExactMatch || Arc.Solid) && (Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/))!=0)
373   {
374     if (ExactMatch)
375     {
376       Log(Arc.FileName,St(MUnpCannotMerge),(char*) ArcFileName);
377 #ifdef RARDLL
378       Cmd->DllError=ERAR_BAD_DATA;
379 #endif
380         ErrHandler.SetErrorCode(WARNING);
381     }
382     ExactMatch=false;
383   }
384
385   FirstFile=false;
386 #endif
387
388   if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
389   {
390     if (Arc.NewLhd.Flags & LHD_PASSWORD)
391 #ifndef RARDLL
392       if (*Password==0)
393 #endif
394       {
395 #ifdef RARDLL
396         if (*Cmd->Password==0)
397           if (Cmd->Callback==NULL ||
398               Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
399             return(false);
400         strcpy(Password,Cmd->Password);
401
402 #else
403         if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
404         {
405                 PasswordCancelled=true;        
406           return(false);
407         }
408 #endif
409       }
410 #if !defined(GUI) && !defined(SILENT)
411       else
412         if (!PasswordAll && (!Arc.Solid || Arc.NewLhd.UnpVer>=20 && (Arc.NewLhd.Flags & LHD_SOLID)==0))
413         {
414           eprintf(St(MUseCurPsw),(char*) ArcFileName);
415           switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
416           {
417             case -1:
418               ErrHandler.Exit(USER_BREAK);
419             case 2:
420               if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
421               {
422                 return(false);
423               }
424               break;
425             case 3:
426               PasswordAll=true;
427               break;
428           }
429         }
430 #endif
431
432 #ifndef SFX_MODULE
433     if (*Cmd->ExtrPath==0 && *Cmd->ExtrPathW!=0)
434       WideToChar(Cmd->ExtrPathW,DestFileName);
435     else
436 #endif
437       strcpy(DestFileName,Cmd->ExtrPath);
438
439
440 #ifndef SFX_MODULE
441     if (Cmd->AppendArcNameToPath)
442     {
443       AddEndSlash(DestFileName);
444       strcat(DestFileName,PointToName(Arc.FileName));
445       SetExt(DestFileName,NULL);
446       AddEndSlash(DestFileName);
447     }
448 #endif
449
450     char *ExtrName=ArcFileName;
451
452     bool EmptyName=false;
453 #ifndef SFX_MODULE
454     int Length=strlen(Cmd->ArcPath);
455     if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) &&
456         strlen(ArcFileName)==((unsigned int)Length-1))
457       Length--;
458     if (Length>0 && strnicomp(Cmd->ArcPath,ArcFileName,Length)==0)
459     {
460       ExtrName+=Length;
461       while (*ExtrName==CPATHDIVIDER)
462         ExtrName++;
463       if (*ExtrName==0)
464         EmptyName=true;
465     }
466 #endif
467
468     bool AbsPaths=Cmd->ExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':');
469     if (AbsPaths)
470       *DestFileName=0;
471
472     if (DestFileName[strlen(DestFileName)-1] != '\\' && DestFileName[strlen(DestFileName)-1] != '/')
473       strcat(DestFileName,"\\");
474       
475     if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
476     {
477       strcat(DestFileName,PointToName(ExtrName));
478     }
479     else
480       strcat(DestFileName,ExtrName);
481
482     if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]))
483       DestFileName[1]=':';
484
485 #ifndef SFX_MODULE
486     if (!WideName && *Cmd->ExtrPathW!=0)
487     {
488       DestNameW=DestFileNameW;
489       WideName=true;
490       CharToWide(ArcFileName,ArcFileNameW);
491     }
492 #endif
493
494     if (WideName)
495     {
496       if (*Cmd->ExtrPathW!=0)
497         strcpyw(DestFileNameW,Cmd->ExtrPathW);
498       else
499         CharToWide(Cmd->ExtrPath,DestFileNameW);
500
501 #ifndef SFX_MODULE
502       if (Cmd->AppendArcNameToPath)
503       {
504         // wchar FileNameW[NM];
505     CSmartStrW FileNameW(NM);
506         if (*Arc.FileNameW!=0)
507           strcpyw(FileNameW,Arc.FileNameW);
508         else
509           CharToWide(Arc.FileName,FileNameW);
510         strcatw(DestFileNameW,PointToName(FileNameW));
511         SetExt(DestFileNameW,NULL);
512         AddEndSlash(DestFileNameW);
513       }
514 #endif
515       wchar *ExtrNameW=ArcFileNameW;
516 #ifndef SFX_MODULE
517       if (Length>0)
518       {
519         // wchar 
520     CSmartStrW ArcPathW(NM);
521         CharToWide(Cmd->ArcPath,ArcPathW);
522         Length=strlenw(ArcPathW);
523       }
524       ExtrNameW+=Length;
525       while (*ExtrNameW==CPATHDIVIDER)
526         ExtrNameW++;
527 #endif
528
529       if (AbsPaths)
530         *DestFileNameW=0;
531
532       if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
533         strcatw(DestFileNameW,PointToName(ExtrNameW));
534       else
535         strcatw(DestFileNameW,ExtrNameW);
536
537       if (AbsPaths && DestFileNameW[1]=='_' && IsPathDiv(DestFileNameW[2]))
538         DestFileNameW[1]=':';
539     }
540     else
541       *DestFileNameW=0;
542
543     ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0/* && *ExtrName*/;
544     if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
545     {
546       struct FindData FD;
547       if (FindFile::FastFind(DestFileName,DestNameW,&FD))
548       {
549         if (FD.mtime >= Arc.NewLhd.mtime)
550           ExtrFile=false;
551       }
552       else
553         if (Cmd->FreshFiles)
554           ExtrFile=false;
555     }
556
557 #ifdef RARDLL
558     if (*Cmd->DllDestName)
559     {
560       strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName));
561       *DestFileNameW=0;
562       if (Cmd->DllOpMode!=RAR_EXTRACT)
563         ExtrFile=false;
564     }
565     if (*Cmd->DllDestNameW)
566     {
567       strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0]));
568       DestNameW=DestFileNameW;
569       if (Cmd->DllOpMode!=RAR_EXTRACT)
570         ExtrFile=false;
571     }
572 #endif
573
574 #ifdef SFX_MODULE
575     if (Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.Method!=0x30)
576 #else
577     if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
578 #endif
579     {
580 #ifndef SILENT
581       Log(Arc.FileName,St(MUnknownMeth),(char*) ArcFileName);
582 #ifndef SFX_MODULE
583       Log(Arc.FileName,St(MVerRequired),Arc.NewLhd.UnpVer/10,Arc.NewLhd.UnpVer%10);
584 #endif
585 #endif
586       ExtrFile=false;
587       ErrHandler.SetErrorCode(WARNING);
588 #ifdef RARDLL
589       Cmd->DllError=ERAR_UNKNOWN_FORMAT;
590 #endif
591     }
592
593     File CurFile;
594
595     if (!IsLink(Arc.NewLhd.FileAttr))
596     {
597       if (Arc.IsArcDir())
598       {
599         if (!ExtrFile || Command=='P' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
600           return(true);
601         if (SkipSolid)
602         {
603 #ifndef GUI
604           mprintf(St(MExtrSkipFile),(char*) ArcFileName);
605 #endif
606           return(true);
607         }
608         TotalFileCount++;
609         if (Cmd->Test)
610         {
611 #ifndef GUI
612           mprintf(St(MExtrTestFile),(char*) ArcFileName);
613           mprintf(" %s",St(MOk));
614 #endif
615           return(true);
616         }
617         if (CUtil::CreateDirectoryEx(DestFileName))
618         {
619 #ifndef GUI
620           mprintf(St(MCreatDir),DestFileName);
621           mprintf(" %s",St(MOk));
622 #endif
623           PrevExtracted=true;
624           SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
625           PrevExtracted=true;
626         }
627         else
628         {
629           Log(Arc.FileName,St(MExtrErrMkDir),DestFileName);
630           ErrHandler.SysErrMsg();
631 #ifdef RARDLL
632           Cmd->DllError=ERAR_ECREATE;
633 #endif
634           ErrHandler.SetErrorCode(CREATE_ERROR);
635         }
636         if (PrevExtracted)
637           SetDirTime(DestFileName,
638             Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
639             Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
640             Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
641         return(true);
642       }
643       else
644       {
645         if (Cmd->Test && ExtrFile)
646           TestMode=true;
647 #if !defined(GUI) && !defined(SFX_MODULE)
648         if (Command=='P' && ExtrFile)
649           CurFile.SetHandleType(FILE_HANDLESTD);
650 #endif
651         if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test)
652         {
653           bool UserReject;
654
655           if (GetDataIO().UnpackToMemorySize == -1) 
656           {
657             if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.UnpSize,Arc.NewLhd.FileTime))
658             {
659               ExtrFile=false;
660               if (!UserReject)
661               {
662                 ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
663                 ErrHandler.SetErrorCode(CREATE_ERROR);
664 #ifdef RARDLL
665                 Cmd->DllError=ERAR_ECREATE;
666 #endif
667               }
668             }
669           }
670         }
671       }
672     }
673     if (!ExtrFile && Arc.Solid)
674     {
675       SkipSolid=true;
676       TestMode=true;
677       ExtrFile=true;
678     }
679     if (ExtrFile)
680     {
681       if (!SkipSolid)
682       {
683         if (!TestMode && Command!='P' && CurFile.IsDevice())
684         {
685           Log(Arc.FileName,St(MInvalidName),DestFileName);
686           ErrHandler.WriteError(Arc.FileName,DestFileName);
687         }
688         TotalFileCount++;
689       }
690       FileCount++;
691 #ifndef GUI
692       if (Command!='I')
693       {
694         if (SkipSolid)
695           mprintf(St(MExtrSkipFile),(char*) ArcFileName);
696         else
697         {
698           switch(Cmd->Test ? 'T':Command)
699           {
700             case 'T':
701               mprintf(St(MExtrTestFile),(char*) ArcFileName);
702               break;
703 #ifndef SFX_MODULE
704             case 'P':
705               mprintf(St(MExtrPrinting),(char*) ArcFileName);
706               break;
707 #endif
708             case 'X':
709             case 'E':
710               mprintf(St(MExtrFile),DestFileName);
711               break;
712           }
713         }
714       }
715       if (!Cmd->DisablePercentage)
716       {
717         mprintf("     ");
718       }
719 #endif
720       DataIO.CurUnpRead=0;
721       DataIO.CurUnpWrite=0;
722       DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
723       DataIO.PackedCRC=0xffffffff;
724       DataIO.SetEncryption(
725         (Arc.NewLhd.Flags & LHD_PASSWORD) ? Arc.NewLhd.UnpVer:0,Password,
726         (Arc.NewLhd.Flags & LHD_SALT) ? Arc.NewLhd.Salt:NULL,false);
727       DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
728       DataIO.SetFiles(&Arc,&CurFile);
729       DataIO.SetTestMode(TestMode);
730       DataIO.SetSkipUnpCRC(SkipSolid);
731
732 #ifndef _WIN_CE
733       if (!TestMode && !Arc.BrokenFileHeader &&
734          (Arc.NewLhd.FullPackSize<<11)>Arc.NewLhd.FullUnpSize &&
735       (Arc.NewLhd.FullUnpSize<100000000 || Arc.FileLength()>Arc.NewLhd.FullPackSize))
736     CurFile.Prealloc(Arc.NewLhd.FullUnpSize);
737 #endif
738     CurFile.SetAllowDelete(!Cmd->KeepBroken);
739
740       bool LinkCreateMode=!Cmd->Test && !SkipSolid;
741       if (ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,LinkCreateMode))
742         PrevExtracted=LinkCreateMode;
743       else if ((Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0)
744       {
745         if (Arc.NewLhd.Method==0x30)
746           UnstoreFile(DataIO,Arc.NewLhd.FullUnpSize);
747         else
748         {
749           Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
750 #ifndef SFX_MODULE        
751           if (Arc.NewLhd.UnpVer<=15)
752             Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
753           else
754 #endif
755             Unp->DoUnpack(Arc.NewLhd.UnpVer,(Arc.NewLhd.Flags & LHD_SOLID));
756         }
757       }
758
759       if (DataIO.UnpackToMemorySize > -1)
760         if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
761         {
762           return false;
763         }
764
765       if (Arc.IsOpened())
766       Arc.SeekToNext();
767
768     bool BrokenFile=false;
769 /*    if (!SkipSolid)
770     {
771       if (Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) ||
772         !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff))
773       {
774 #ifndef GUI
775       if (Command!='P' && Command!='I')
776         mprintf("%s%s ",Cmd->DisablePercentage ? " ":"\b\b\b\b\b ",St(MOk));
777 #endif
778       }
779       else
780       {
781         char *BadArcName=(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE) ? NULL:Arc.FileName;
782         if (Arc.NewLhd.Flags & LHD_PASSWORD)
783         {
784           Log(BadArcName,St(MEncrBadCRC),ArcFileName);
785         }
786         else
787         {
788           Log(BadArcName,St(MCRCFailed),ArcFileName);
789         }
790         BrokenFile=true;
791         ErrHandler.SetErrorCode(CRC_ERROR);
792 #ifdef RARDLL
793         Cmd->DllError=ERAR_BAD_DATA;
794 #endif
795         Alarm();
796       }
797     }*/
798 #ifndef GUI
799 //    else
800 //      mprintf("\b\b\b\b\b     ");
801 #endif
802
803     if (!TestMode && (Command=='X' || Command=='E') &&
804       !IsLink(Arc.NewLhd.FileAttr))
805     {
806 #if defined(_WIN_32) || defined(_EMX)
807       if (Cmd->ClearArc)
808         Arc.NewLhd.FileAttr&=~FA_ARCH;
809 #endif
810       if (!BrokenFile || Cmd->KeepBroken)
811       {
812         if (BrokenFile)
813           CurFile.Truncate();
814         CurFile.SetOpenFileStat(
815           Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
816           Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
817           Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
818         CurFile.Close();
819           CurFile.SetCloseFileStat(
820           Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
821           Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime,
822           Arc.NewLhd.FileAttr);
823           PrevExtracted=true;
824         }
825       }
826     }
827   }
828   if (ExactMatch)
829     MatchedArgs++;
830   if (DataIO.NextVolumeMissing || !Arc.IsOpened())
831     return(false);
832   if (!ExtrFile)
833   {
834     if (!Arc.Solid)
835       Arc.SeekToNext();
836     else if (!SkipSolid)
837       return(false);
838   }
839   return(true);
840 }
841
842
843 void CmdExtract::UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize)
844 {
845   Array<byte> Buffer(0x40000);
846   if (DataIO.UnpackToMemorySize > -1)
847   {
848     while (1)
849     {
850       if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
851       {
852         return;
853       }
854       int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
855       if (DataIO.UnpackToMemorySize > -1 && !DataIO.NextVolumeMissing)
856       {
857         if (WaitForSingleObject(DataIO.hSeek,1) == WAIT_OBJECT_0)
858           continue;
859       }
860       if (Code > 0)
861       {
862         Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
863         DataIO.UnpWrite(&Buffer[0],Code);
864         if (DestUnpSize>=0)
865           DestUnpSize-=Code;
866       }
867       else 
868       {
869         if (DataIO.NextVolumeMissing)
870           SetEvent(DataIO.hSeekDone);
871         else 
872         if (WaitForSingleObject(DataIO.hSeek,1) == WAIT_OBJECT_0)
873            continue;
874         ResetEvent(DataIO.hBufferFilled);
875         SetEvent(DataIO.hBufferEmpty);
876         while (WaitForSingleObject(DataIO.hBufferFilled,1) != WAIT_OBJECT_0)
877           if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
878             return;
879       }
880     }
881   }
882   else
883   {
884     while (1)
885     {
886       int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
887       if (Code > 0)
888       {
889         Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
890         DataIO.UnpWrite(&Buffer[0],Code);
891         if (DestUnpSize>=0)
892           DestUnpSize-=Code;
893       }
894       else if (Code == -1)
895       {
896         DataIO.NextVolumeMissing = true;
897         return;
898       }
899       else
900         return;
901     }
902   }
903 }