~ubuntu-branches/ubuntu/vivid/unrar-nonfree/vivid

« back to all changes in this revision

Viewing changes to extract.cpp

  • Committer: Package Import Robot
  • Author(s): Martin Meredith
  • Date: 2015-02-03 12:58:01 UTC
  • mfrom: (1.1.18) (5.1.18 sid)
  • Revision ID: package-import@ubuntu.com-20150203125801-od6ev8cqy1er51vz
Tags: 1:5.2.5-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
CmdExtract::CmdExtract(CommandData *Cmd)
4
4
{
 
5
  CmdExtract::Cmd=Cmd;
 
6
 
5
7
  *ArcName=0;
6
8
 
7
9
  *DestFileName=0;
8
10
 
9
11
  TotalFileCount=0;
10
 
  Password.Set(L"");
11
12
  Unp=new Unpack(&DataIO);
12
13
#ifdef RAR_SMP
13
14
  Unp->SetThreads(Cmd->Threads);
21
22
}
22
23
 
23
24
 
24
 
void CmdExtract::DoExtract(CommandData *Cmd)
 
25
void CmdExtract::DoExtract()
25
26
{
 
27
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
 
28
  Fat32=NotFat32=false;
 
29
#endif
26
30
  PasswordCancelled=false;
27
31
  DataIO.SetCurrentCommand(Cmd->Command[0]);
28
32
 
34
38
  Cmd->ArcNames.Rewind();
35
39
  while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
36
40
  {
 
41
    if (Cmd->ManualPassword)
 
42
      Cmd->Password.Clean(); // Clean user entered password before processing next archive.
37
43
    while (true)
38
44
    {
39
 
      SecPassword PrevCmdPassword;
40
 
      PrevCmdPassword=Cmd->Password;
41
 
 
42
 
      EXTRACT_ARC_CODE Code=ExtractArchive(Cmd);
43
 
 
44
 
      // Restore Cmd->Password, which could be changed in IsArchive() call
45
 
      // for next header encrypted archive.
46
 
      Cmd->Password=PrevCmdPassword;
47
 
 
 
45
      EXTRACT_ARC_CODE Code=ExtractArchive();
48
46
      if (Code!=EXTRACT_ARC_REPEAT)
49
47
        break;
50
48
    }
52
50
      DataIO.ProcessedArcSize+=FD.Size;
53
51
  }
54
52
 
 
53
  // Clean user entered password. Not really required, just for extra safety.
 
54
  if (Cmd->ManualPassword)
 
55
    Cmd->Password.Clean();
 
56
 
55
57
  if (TotalFileCount==0 && Cmd->Command[0]!='I' && 
56
58
      ErrHandler.GetErrorCode()!=RARX_BADPWD) // Not in case of wrong archive password.
57
59
  {
58
60
    if (!PasswordCancelled)
59
 
    {
60
 
      mprintf(St(MExtrNoFiles));
61
 
    }
 
61
      uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName);
62
62
    ErrHandler.SetErrorCode(RARX_NOFILES);
63
63
  }
64
64
#ifndef GUI
75
75
}
76
76
 
77
77
 
78
 
void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
 
78
void CmdExtract::ExtractArchiveInit(Archive &Arc)
79
79
{
80
80
  DataIO.UnpArcSize=Arc.FileLength();
81
81
 
86
86
#endif
87
87
 
88
88
  PasswordAll=(Cmd->Password.IsSet());
89
 
  if (PasswordAll)
90
 
    Password=Cmd->Password;
91
89
 
92
90
  DataIO.UnpVolume=false;
93
91
 
100
98
}
101
99
 
102
100
 
103
 
EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
 
101
EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
104
102
{
105
103
  Archive Arc(Cmd);
106
104
  if (!Arc.WOpen(ArcName))
107
 
  {
108
 
    ErrHandler.SetErrorCode(RARX_OPEN);
109
105
    return EXTRACT_ARC_NEXT;
110
 
  }
111
106
 
112
107
  if (!Arc.IsArchive(true))
113
108
  {
126
121
  if (Arc.Volume && !Arc.FirstVolume)
127
122
  {
128
123
    wchar FirstVolName[NM];
129
 
    VolNameToFirstName(ArcName,FirstVolName,Arc.NewNumbering);
 
124
    VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering);
130
125
 
131
126
    // If several volume names from same volume set are specified
132
127
    // and current volume is not first in set and first volume is present
162
157
    DataIO.TotalArcSize+=VolumeSetSize;
163
158
  }
164
159
 
165
 
  ExtractArchiveInit(Cmd,Arc);
 
160
  ExtractArchiveInit(Arc);
166
161
 
167
162
  if (*Cmd->Command=='T' || *Cmd->Command=='I')
168
163
    Cmd->Test=true;
169
164
 
170
165
 
171
 
#ifndef GUI
172
166
  if (*Cmd->Command=='I')
 
167
  {
 
168
#ifndef GUI   
173
169
    Cmd->DisablePercentage=true;
 
170
#endif
 
171
  }
174
172
  else
175
 
    if (Cmd->Test)
176
 
      mprintf(St(MExtrTest),ArcName);
177
 
    else
178
 
      mprintf(St(MExtracting),ArcName);
179
 
#endif
 
173
    uiStartArchiveExtract(!Cmd->Test,ArcName);
180
174
 
181
175
  Arc.ViewComment();
182
176
 
187
181
 
188
182
 
189
183
    bool Repeat=false;
190
 
    if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
 
184
    if (!ExtractCurrentFile(Arc,Size,Repeat))
191
185
      if (Repeat)
192
186
      {
193
187
        // If we started extraction from not first volume and need to
210
204
}
211
205
 
212
206
 
213
 
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,bool &Repeat)
 
207
bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
214
208
{
215
209
  wchar Command=Cmd->Command[0];
216
210
  if (HeaderSize==0)
219
213
#ifdef NOVOLUME
220
214
      return false;
221
215
#else
 
216
      // Supposing we unpack an old RAR volume without end of archive record
 
217
      // and last file is not split between volumes.
222
218
      if (!MergeArchive(Arc,&DataIO,false,Command))
223
219
      {
224
220
        ErrHandler.SetErrorCode(RARX_WARNING);
263
259
  int MatchType=MATCH_WILDSUBPATH;
264
260
 
265
261
  bool EqualNames=false;
266
 
  int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType);
267
 
  bool ExactMatch=MatchNumber!=0;
 
262
  wchar MatchedArg[NM];
 
263
  int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg));
 
264
  bool MatchFound=MatchNumber!=0;
268
265
#ifndef SFX_MODULE
269
266
  if (Cmd->ExclPath==EXCL_BASEPATH)
270
267
  {
271
 
    *Cmd->ArcPath=0;
272
 
    if (ExactMatch)
273
 
    {
274
 
      Cmd->FileArgs.Rewind();
275
 
      if (Cmd->FileArgs.GetString(Cmd->ArcPath,ASIZE(Cmd->ArcPath),MatchNumber-1))
276
 
        *PointToName(Cmd->ArcPath)=0;
277
 
    }
 
268
    wcsncpyz(Cmd->ArcPath,MatchedArg,ASIZE(Cmd->ArcPath));
 
269
    *PointToName(Cmd->ArcPath)=0;
 
270
    if (IsWildcard(Cmd->ArcPath)) // Cannot correctly process path*\* masks here.
 
271
      *Cmd->ArcPath=0;
278
272
  }
279
273
#endif
280
 
  if (ExactMatch && !EqualNames)
 
274
  if (MatchFound && !EqualNames)
281
275
    AllMatchesExact=false;
282
276
 
283
277
  Arc.ConvertAttributes();
287
281
  {
288
282
    wchar CurVolName[NM];
289
283
    wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName));
290
 
    VolNameToFirstName(ArcName,ArcName,Arc.NewNumbering);
 
284
    VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering);
291
285
 
292
286
    if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
293
287
    {
300
294
    if (!ReconstructDone)
301
295
    {
302
296
      ReconstructDone=true;
303
 
 
304
297
      if (RecVolumesRestore(Cmd,Arc.FileName,true))
305
298
      {
306
299
        Repeat=true;
320
313
    if (Cmd->VersionControl!=1 && !EqualNames)
321
314
    {
322
315
      if (Cmd->VersionControl==0)
323
 
        ExactMatch=false;
 
316
        MatchFound=false;
324
317
      int Version=ParseVersionFileName(ArcFileName,false);
325
318
      if (Cmd->VersionControl-1==Version)
326
319
        ParseVersionFileName(ArcFileName,true);
327
320
      else
328
 
        ExactMatch=false;
 
321
        MatchFound=false;
329
322
    }
330
323
  }
331
324
  else
332
325
    if (!Arc.IsArcDir() && Cmd->VersionControl>1)
333
 
      ExactMatch=false;
 
326
      MatchFound=false;
334
327
 
335
328
  DataIO.UnpVolume=Arc.FileHead.SplitAfter;
336
329
  DataIO.NextVolumeMissing=false;
341
334
  bool SkipSolid=false;
342
335
 
343
336
#ifndef SFX_MODULE
344
 
  if (FirstFile && (ExactMatch || Arc.Solid) && Arc.FileHead.SplitBefore)
 
337
  if (FirstFile && (MatchFound || Arc.Solid) && Arc.FileHead.SplitBefore)
345
338
  {
346
 
    if (ExactMatch)
 
339
    if (MatchFound)
347
340
    {
348
 
      Log(Arc.FileName,St(MUnpCannotMerge),ArcFileName);
 
341
      uiMsg(UIERROR_NEEDPREVVOL,Arc.FileName,ArcFileName);
349
342
#ifdef RARDLL
350
343
      Cmd->DllError=ERAR_BAD_DATA;
351
344
#endif
352
345
      ErrHandler.SetErrorCode(RARX_OPEN);
353
346
    }
354
 
    ExactMatch=false;
 
347
    MatchFound=false;
355
348
  }
356
349
 
357
350
  FirstFile=false;
358
351
#endif
359
352
 
360
 
  if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
 
353
  if (MatchFound || (SkipSolid=Arc.Solid)!=0)
361
354
  {
 
355
    // First common call of uiStartFileExtract. It is done before overwrite
 
356
    // prompts, so if SkipSolid state is changed below, we'll need to make
 
357
    // additional uiStartFileExtract calls with updated parameters.
 
358
    if (!uiStartFileExtract(ArcFileName,!Cmd->Test,Cmd->Test && Command!='I',SkipSolid))
 
359
      return false;
362
360
 
363
 
    ExtrPrepareName(Cmd,Arc,ArcFileName,DestFileName,ASIZE(DestFileName));
 
361
    ExtrPrepareName(Arc,ArcFileName,DestFileName,ASIZE(DestFileName));
364
362
 
365
363
    // DestFileName can be set empty in case of excessive -ap switch.
366
364
    ExtrFile=!SkipSolid && *DestFileName!=0 && !Arc.FileHead.SplitBefore;
390
388
    if (Arc.FileHead.Encrypted)
391
389
    {
392
390
#ifdef RARDLL
393
 
      if (!ExtrDllGetPassword(Cmd))
 
391
      if (!ExtrDllGetPassword())
394
392
        return false;
395
393
#else
396
 
      if (!ExtrGetPassword(Cmd,Arc,ArcFileName))
 
394
      if (!ExtrGetPassword(Arc,ArcFileName))
397
395
      {
398
396
        PasswordCancelled=true;
399
397
        return false;
400
398
      }
401
399
#endif
402
400
      // Skip only the current encrypted file if empty password is entered.
403
 
      if (!Password.IsSet())
 
401
      if (!Cmd->Password.IsSet())
404
402
      {
405
403
        ErrHandler.SetErrorCode(RARX_WARNING);
406
404
#ifdef RARDLL
412
410
 
413
411
#ifdef RARDLL
414
412
    if (*Cmd->DllDestName!=0)
415
 
    {
416
413
      wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
417
 
 
418
 
//      Do we need this code?
419
 
//      if (Cmd->DllOpMode!=RAR_EXTRACT)
420
 
//        ExtrFile=false;
421
 
    }
422
414
#endif
423
415
 
424
416
    if (!CheckUnpVer(Arc,ArcFileName))
425
417
    {
426
418
      ExtrFile=false;
427
 
      ErrHandler.SetErrorCode(RARX_WARNING);
 
419
      ErrHandler.SetErrorCode(RARX_FATAL);
428
420
#ifdef RARDLL
429
421
      Cmd->DllError=ERAR_UNKNOWN_FORMAT;
430
422
#endif
440
432
        // Overwrite prompt for symbolic and hard links.
441
433
        bool UserReject=false;
442
434
        if (FileExist(DestFileName) && !UserReject)
443
 
          FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),Cmd->Overwrite,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
 
435
          FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
444
436
        if (UserReject)
445
437
          ExtrFile=false;
446
438
      }
451
443
        if (!ExtrFile || Command=='P' || Command=='I' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
452
444
          return true;
453
445
        TotalFileCount++;
454
 
        ExtrCreateDir(Cmd,Arc,ArcFileName);
 
446
        ExtrCreateDir(Arc,ArcFileName);
455
447
        return true;
456
448
      }
457
449
      else
458
450
        if (ExtrFile) // Create files and file copies (FSREDIR_FILECOPY).
459
 
          ExtrFile=ExtrCreateFile(Cmd,Arc,CurFile);
 
451
          ExtrFile=ExtrCreateFile(Arc,CurFile);
460
452
 
461
453
    if (!ExtrFile && Arc.Solid)
462
454
    {
463
455
      SkipSolid=true;
464
456
      ExtrFile=true;
465
457
 
 
458
      // We changed SkipSolid, so we need to call uiStartFileExtract
 
459
      // with "Skip" parameter to change the operation status 
 
460
      // from "extracting" to "skipping". For example, it can be necessary
 
461
      // if user answered "No" to overwrite prompt when unpacking
 
462
      // a solid archive.
 
463
      if (!uiStartFileExtract(ArcFileName,false,false,true))
 
464
        return false;
466
465
    }
467
466
    if (ExtrFile)
468
467
    {
472
471
      {
473
472
        if (!TestMode && Command!='P' && CurFile.IsDevice())
474
473
        {
475
 
          Log(Arc.FileName,St(MInvalidName),DestFileName);
 
474
          uiMsg(UIERROR_INVALIDNAME,Arc.FileName,DestFileName);
476
475
          ErrHandler.WriteError(Arc.FileName,DestFileName);
477
476
        }
478
477
        TotalFileCount++;
502
501
        mprintf(L"     ");
503
502
#endif
504
503
 
505
 
      SecPassword FilePassword=Password;
 
504
      SecPassword FilePassword=Cmd->Password;
506
505
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
507
506
      ConvertDosPassword(Arc,FilePassword);
508
507
#endif
520
519
          memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
521
520
          !Arc.BrokenHeader)
522
521
      {
523
 
        Log(Arc.FileName,St(MWrongPassword));
 
522
        uiMsg(UIERROR_BADPSW,Arc.FileName);
524
523
        ErrHandler.SetErrorCode(RARX_BADPWD);
525
524
        WrongPassword=true;
526
525
      }
532
531
      DataIO.SetFiles(&Arc,&CurFile);
533
532
      DataIO.SetTestMode(TestMode);
534
533
      DataIO.SetSkipUnpCRC(SkipSolid);
 
534
 
 
535
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
 
536
      if (!TestMode && !WrongPassword && !Arc.BrokenHeader &&
 
537
          Arc.FileHead.UnpSize>0xffffffff && (Fat32 || !NotFat32))
 
538
      {
 
539
        if (!Fat32) // Not detected yet.
 
540
          NotFat32=!(Fat32=IsFAT(Cmd->ExtrPath));
 
541
        if (Fat32)
 
542
          uiMsg(UIMSG_FAT32SIZE); // Inform user about FAT32 size limit.
 
543
      }
 
544
#endif
 
545
 
535
546
      if (!TestMode && !WrongPassword && !Arc.BrokenHeader &&
536
547
          (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
537
548
          (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
542
553
      bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
543
554
      bool ShowChecksum=true; // Display checksum verification result.
544
555
 
 
556
      bool LinkSuccess=true; // Assume success for test mode.
545
557
      if (LinkEntry)
546
558
      {
547
559
        FILE_SYSTEM_REDIRECT Type=Arc.FileHead.RedirType;
548
560
 
549
 
        bool LinkSuccess=true; // Assume success for test mode.
550
561
        if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY)
551
562
        {
552
563
          wchar NameExisting[NM];
553
 
          ExtrPrepareName(Cmd,Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting));
 
564
          ExtrPrepareName(Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting));
554
565
          if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch.
555
566
            if (Type==FSREDIR_HARDLINK)
556
567
              LinkSuccess=ExtractHardlink(DestFileName,NameExisting,ASIZE(NameExisting));
565
576
          }
566
577
          else
567
578
          {
568
 
#ifndef SFX_MODULE
569
 
            Log(Arc.FileName,St(MUnknownExtra),DestFileName);
570
 
#endif
 
579
            uiMsg(UIERROR_UNKNOWNEXTRA, Arc.FileName, DestFileName);
571
580
            LinkSuccess=false;
572
581
          }
573
582
          
588
597
            UnstoreFile(DataIO,Arc.FileHead.UnpSize);
589
598
          else
590
599
          {
 
600
#ifdef _ANDROID
 
601
            // malloc and new do not report memory allocation errors
 
602
            // in Android, so if free memory is set, check it here
 
603
            // trying to prevent crash.
 
604
            if (Cmd->FreeMem!=0 && Cmd->FreeMem < Arc.FileHead.WinSize)
 
605
              throw std::bad_alloc();
 
606
#endif
591
607
            Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
592
608
            Unp->SetDestSize(Arc.FileHead.UnpSize);
593
609
#ifndef SFX_MODULE
600
616
 
601
617
      Arc.SeekToNext();
602
618
 
603
 
      bool ValidCRC=DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL);
 
619
      // We check for "split after" flag to detect partially extracted files
 
620
      // from incomplete volume sets. For them file header contains packed
 
621
      // data hash, which must not be compared against unpacked data hash
 
622
      // to prevent accidental match. Moreover, for -m0 volumes packed data
 
623
      // hash would match truncated unpacked data hash and lead to fake "OK"
 
624
      // in incomplete volume set.
 
625
      bool ValidCRC=!Arc.FileHead.SplitAfter && DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL);
604
626
 
605
627
      // We set AnySolidDataUnpackedWell to true if we found at least one
606
628
      // valid non-zero solid file in preceding solid stream. If it is true
615
637
      bool BrokenFile=false;
616
638
      
617
639
      // Checksum is not calculated in skip solid mode for performance reason.
618
 
      if (!SkipSolid)
 
640
      if (!SkipSolid && ShowChecksum)
619
641
      {
620
642
        if (!WrongPassword && ValidCRC)
621
643
        {
622
644
#ifndef GUI
623
 
          if (Command!='P' && Command!='I' && ShowChecksum)
 
645
          if (Command!='P' && Command!='I')
624
646
            mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ",
625
647
              Arc.FileHead.FileHash.Type==HASH_NONE ? L"  ?":St(MOk));
626
648
#endif
630
652
          if (!WrongPassword)
631
653
            if (Arc.FileHead.Encrypted && (!Arc.FileHead.UsePswCheck || 
632
654
                Arc.BrokenHeader) && !AnySolidDataUnpackedWell)
633
 
            {
634
 
              Log(Arc.FileName,St(MEncrBadCRC),ArcFileName);
635
 
            }
 
655
              uiMsg(UIERROR_CHECKSUMENC,Arc.FileName,ArcFileName);
636
656
            else
637
 
            {
638
 
              Log(Arc.FileName,St(MCRCFailed),ArcFileName);
639
 
            }
 
657
              uiMsg(UIERROR_CHECKSUM,Arc.FileName,ArcFileName);
640
658
          BrokenFile=true;
641
659
          ErrHandler.SetErrorCode(RARX_CRC);
642
660
#ifdef RARDLL
643
661
          // If we already have ERAR_EOPEN as result of missing volume,
644
662
          // we should not replace it with less precise ERAR_BAD_DATA.
645
663
          if (Cmd->DllError!=ERAR_EOPEN)
646
 
            Cmd->DllError=ERAR_BAD_DATA;
 
664
            Cmd->DllError=WrongPassword ? ERAR_BAD_PASSWORD : ERAR_BAD_DATA;
647
665
#endif
648
666
        }
649
667
      }
653
671
#endif
654
672
 
655
673
      if (!TestMode && !WrongPassword && (Command=='X' || Command=='E') &&
656
 
          (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY) && 
 
674
          (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && 
657
675
          (!BrokenFile || Cmd->KeepBroken))
658
676
      {
659
677
        // We could preallocate more space that really written to broken file.
684
702
        CurFile.SetCloseFileTime(
685
703
          Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
686
704
          Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
687
 
        if (!Cmd->IgnoreGeneralAttr)
688
 
          SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr);
 
705
        if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr))
 
706
          uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName);
 
707
 
689
708
        PrevExtracted=true;
690
709
      }
691
710
    }
692
711
  }
693
 
  if (ExactMatch)
 
712
  if (MatchFound)
694
713
    MatchedArgs++;
695
714
  if (DataIO.NextVolumeMissing)
696
715
    return false;
706
725
 
707
726
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
708
727
{
709
 
  Array<byte> Buffer(0x100000);
 
728
  // 512 KB and larger buffer reported to reduce performance on old XP
 
729
  // computers with WDC WD2000JD HDD. According to test made by user
 
730
  // 256 KB buffer is optimal.
 
731
  Array<byte> Buffer(0x40000);
710
732
  while (1)
711
733
  {
712
734
    uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
722
744
 
723
745
bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
724
746
{
725
 
#ifdef _WIN_ALL
726
 
  UnixSlashToDos(NameExisting,NameExisting,NameExistingSize);
727
 
#elif defined(_UNIX)
728
 
  DosSlashToUnix(NameExisting,NameExisting,NameExistingSize);
729
 
#endif
 
747
  SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
 
748
 
730
749
  File Existing;
731
 
  if (!Existing.Open(NameExisting))
 
750
  if (!Existing.WOpen(NameExisting))
732
751
  {
733
 
    ErrHandler.OpenErrorMsg(ArcName,NameExisting);
734
 
    Log(ArcName,St(MCopyError),NameExisting,NameNew);
735
 
    Log(ArcName,St(MCopyErrorHint));
 
752
    uiMsg(UIERROR_FILECOPY,ArcName,NameExisting,NameNew);
 
753
    uiMsg(UIERROR_FILECOPYHINT,ArcName);
 
754
#ifdef RARDLL
 
755
    Cmd->DllError=ERAR_EREFERENCE;
 
756
#endif
736
757
    return false;
737
758
  }
738
759
 
753
774
}
754
775
 
755
776
 
756
 
void CmdExtract::ExtrPrepareName(CommandData *Cmd,Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize)
 
777
void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize)
757
778
{
758
779
  wcsncpyz(DestName,Cmd->ExtrPath,DestSize);
759
780
 
769
790
  if (Cmd->AppendArcNameToPath)
770
791
  {
771
792
    wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
772
 
    SetExt(DestName,NULL);
 
793
    SetExt(DestName,NULL,DestSize);
773
794
    AddEndSlash(DestName,DestSize);
774
795
  }
775
796
#endif
823
844
 
824
845
 
825
846
#ifdef RARDLL
826
 
bool CmdExtract::ExtrDllGetPassword(CommandData *Cmd)
 
847
bool CmdExtract::ExtrDllGetPassword()
827
848
{
828
849
  if (!Cmd->Password.IsSet())
829
850
  {
844
865
      }
845
866
      Cmd->Password.Set(PasswordW);
846
867
      cleandata(PasswordW,sizeof(PasswordW));
 
868
      Cmd->ManualPassword=true;
847
869
    }
848
870
    if (!Cmd->Password.IsSet())
849
871
      return false;
850
872
  }
851
 
  Password=Cmd->Password;
852
873
  return true;
853
874
}
854
875
#endif
855
876
 
856
877
 
857
878
#ifndef RARDLL
858
 
bool CmdExtract::ExtrGetPassword(CommandData *Cmd,Archive &Arc,const wchar *ArcFileName)
 
879
bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
859
880
{
860
 
  if (!Password.IsSet())
 
881
  if (!Cmd->Password.IsSet())
861
882
  {
862
 
    if (!GetPassword(PASSWORD_FILE,ArcFileName,&Password))
 
883
    if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password) || !Cmd->Password.IsSet())
863
884
    {
 
885
      // Suppress "test is ok" message in GUI if user entered
 
886
      // an empty password or cancelled a password prompt.
 
887
      uiMsg(UIERROR_INCERRCOUNT);
 
888
 
864
889
      return false;
865
890
    }
 
891
    Cmd->ManualPassword=true;
866
892
  }
867
893
#if !defined(GUI) && !defined(SILENT)
868
894
  else
869
895
    if (!PasswordAll && !Arc.FileHead.Solid)
870
896
    {
871
897
      eprintf(St(MUseCurPsw),ArcFileName);
872
 
      switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
 
898
      switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll)))
873
899
      {
874
900
        case -1:
875
901
          ErrHandler.Exit(RARX_USERBREAK);
876
902
        case 2:
877
 
          if (!GetPassword(PASSWORD_FILE,ArcFileName,&Password))
 
903
          if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password))
878
904
            return false;
879
905
          break;
880
906
        case 3:
896
922
    // We need the password in OEM encoding if file was encrypted by
897
923
    // native RAR/DOS (not extender based). Let's make the conversion.
898
924
    wchar PlainPsw[MAXPASSWORD];
899
 
    Password.Get(PlainPsw,ASIZE(PlainPsw));
 
925
    Cmd->Password.Get(PlainPsw,ASIZE(PlainPsw));
900
926
    char PswA[MAXPASSWORD];
901
927
    CharToOemBuffW(PlainPsw,PswA,ASIZE(PswA));
902
928
    PswA[ASIZE(PswA)-1]=0;
909
935
#endif
910
936
 
911
937
 
912
 
void CmdExtract::ExtrCreateDir(CommandData *Cmd,Archive &Arc,const wchar *ArcFileName)
 
938
void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
913
939
{
914
940
  if (Cmd->Test)
915
941
  {
930
956
      // File with name same as this directory exists. Propose user
931
957
      // to overwrite it.
932
958
      bool UserReject;
933
 
      FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),Cmd->Overwrite,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
 
959
      FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
934
960
      DirExist=false;
935
961
    }
936
962
    if (!DirExist)
937
963
    {
938
964
      CreatePath(DestFileName,true);
939
965
      MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
 
966
      if (MDCode!=MKDIR_SUCCESS)
 
967
      {
 
968
        wchar OrigName[ASIZE(DestFileName)];
 
969
        wcsncpyz(OrigName,DestFileName,ASIZE(OrigName));
 
970
        MakeNameUsable(DestFileName,true);
 
971
        CreatePath(DestFileName,true);
 
972
        MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
 
973
#ifndef SFX_MODULE
 
974
        if (MDCode==MKDIR_SUCCESS)
 
975
          uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName);
 
976
#endif
 
977
      }
940
978
    }
941
979
  }
942
980
  if (MDCode==MKDIR_SUCCESS)
956
994
    }
957
995
    else
958
996
    {
959
 
      Log(Arc.FileName,St(MExtrErrMkDir),DestFileName);
960
 
      ErrHandler.CheckLongPathErrMsg(DestFileName);
 
997
      uiMsg(UIERROR_DIRCREATE,Arc.FileName,DestFileName);
961
998
      ErrHandler.SysErrMsg();
962
999
#ifdef RARDLL
963
1000
      Cmd->DllError=ERAR_ECREATE;
979
1016
}
980
1017
 
981
1018
 
982
 
bool CmdExtract::ExtrCreateFile(CommandData *Cmd,Archive &Arc,File &CurFile)
 
1019
bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile)
983
1020
{
984
1021
  bool Success=true;
985
1022
  wchar Command=Cmd->Command[0];
992
1029
    bool UserReject;
993
1030
    // Specify "write only" mode to avoid OpenIndiana NAS problems
994
1031
    // with SetFileTime and read+write files.
995
 
    if (!FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),Cmd->Overwrite,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
 
1032
    if (!FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
996
1033
    {
997
1034
      Success=false;
998
1035
      if (!UserReject)
999
1036
      {
1000
1037
        ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
1001
 
        ErrHandler.SetErrorCode(RARX_CREATE);
1002
1038
#ifdef RARDLL
1003
1039
        Cmd->DllError=ERAR_ECREATE;
1004
1040
#endif
1005
1041
        if (!IsNameUsable(DestFileName))
1006
1042
        {
1007
 
          Log(Arc.FileName,St(MCorrectingName));
 
1043
          uiMsg(UIMSG_CORRECTINGNAME,Arc.FileName);
 
1044
 
1008
1045
          wchar OrigName[ASIZE(DestFileName)];
1009
1046
          wcsncpyz(OrigName,DestFileName,ASIZE(OrigName));
1010
1047
 
1011
1048
          MakeNameUsable(DestFileName,true);
1012
1049
 
1013
1050
          CreatePath(DestFileName,true);
1014
 
          if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),Cmd->Overwrite,&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
 
1051
          if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
1015
1052
          {
1016
1053
#ifndef SFX_MODULE
1017
 
            Log(Arc.FileName,St(MRenaming),OrigName,DestFileName);
 
1054
            uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName);
1018
1055
#endif
1019
1056
            Success=true;
1020
1057
          }
1048
1085
 
1049
1086
  if (WrongVer)
1050
1087
  {
1051
 
#ifndef SILENT
1052
 
    Log(Arc.FileName,St(MUnknownMeth),ArcFileName);
1053
 
#ifndef SFX_MODULE
1054
 
//      Log(Arc.FileName,St(MVerRequired),Arc.FileHead.UnpVer/10,Arc.FileHead.UnpVer%10);
1055
 
    Log(Arc.FileName,St(MNewerRAR));
1056
 
#endif
1057
 
#endif
 
1088
    ErrHandler.UnknownMethodMsg(Arc.FileName,ArcFileName);
 
1089
    uiMsg(UIERROR_NEWERRAR,Arc.FileName);
1058
1090
  }
1059
1091
  return !WrongVer;
1060
1092
}