Exemplo n.º 1
0
void ConvertNameToFull(const wchar *Src,wchar *Dest)
{
  if (Src==NULL || *Src==0)
  {
    *Dest=0;
    return;
  }
#ifdef _WIN_32
  if (WinNT())
  {
    wchar FullName[NM],*NamePtr;
    if (GetFullPathNameW(Src,sizeof(FullName)/sizeof(FullName[0]),FullName,&NamePtr))
      strcpyw(Dest,FullName);
    else
      if (Src!=Dest)
        strcpyw(Dest,Src);
  }
  else
  {
    char AnsiName[NM];
    WideToChar(Src,AnsiName);
    ConvertNameToFull(AnsiName,AnsiName);
    CharToWide(AnsiName,Dest);
  }
#else
  char AnsiName[NM];
  WideToChar(Src,AnsiName);
  ConvertNameToFull(AnsiName,AnsiName);
  CharToWide(AnsiName,Dest);
#endif
}
Exemplo n.º 2
0
void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
{
  if (!WinNT())
    return;

  wchar NameW[NM];
  if (FileNameW!=NULL && *FileNameW!=0)
    strcpyw(NameW,FileNameW);
  else
    CharToWide(FileName,NameW);
  wchar StreamNameW[NM+2];
  if (NameW[0]!=0 && NameW[1]==0)
  {
    strcpyw(StreamNameW,L".\\");
    strcpyw(StreamNameW+2,NameW);
  }
  else
    strcpyw(StreamNameW,NameW);

  wchar *DestName=StreamNameW+strlenw(StreamNameW);
  byte *SrcName=&Arc.SubHead.SubData[0];
  int DestSize=Arc.SubHead.SubData.Size()/2;

  if (strlenw(StreamNameW)+DestSize>=sizeof(StreamNameW)/sizeof(StreamNameW[0]))
  {
#if !defined(SILENT) && !defined(SFX_MODULE)
    Log(Arc.FileName,St(MStreamBroken),FileName);
#endif
    ErrHandler.SetErrorCode(CRC_ERROR);
    return;
  }

  RawToWide(SrcName,DestName,DestSize);
  DestName[DestSize]=0;

  FindData fd;
  bool Found=FindFile::FastFind(FileName,FileNameW,&fd);

  if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
    SetFileAttr(FileName,FileNameW,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);
  char StreamName[NM];
  WideToChar(StreamNameW,StreamName);
  File CurFile;
  if (CurFile.WCreate(StreamName,StreamNameW) && Arc.ReadSubData(NULL,&CurFile))
    CurFile.Close();
  File HostFile;
  if (Found && HostFile.Open(FileName,FileNameW,true,true))
    SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
                &fd.ftLastWriteTime);
  if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
    SetFileAttr(FileName,FileNameW,fd.FileAttr);
}
Exemplo n.º 3
0
bool File::Create(const char *Name,const wchar *NameW)
{
/*#ifdef _WIN_32
  if (WinNT() && NameW!=NULL && *NameW!=0)
    hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                      CREATE_ALWAYS,0,NULL);
  else
    hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                     CREATE_ALWAYS,0,NULL);
#else*/
  hFile=fopen(Name,CREATEBINARY);
//#endif
  NewFile=true;
  HandleType=FILE_HANDLENORMAL;
  SkipClose=false;
  if (NameW!=NULL)
    strcpyw(FileNameW,NameW);
  else
    *FileNameW=0;
  if (Name!=NULL)
    strcpy(FileName,Name);
  else
    WideToChar(NameW,FileName);
  AddFileToList(hFile);
  return(hFile!=BAD_HANDLE);
}
Exemplo n.º 4
0
bool File::Create(const char *Name,const wchar *NameW)
{
    /*#ifdef _WIN_32
    #ifndef _XBOX
      if (WinNT() && NameW!=NULL && *NameW!=0)
        hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                          CREATE_ALWAYS,0,NULL);
      else
    #endif
        hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                         CREATE_ALWAYS,0,NULL);
    #else
      hFile=fopen(Name,CREATEBINARY);
    #endif*/
    CStdString strPath;
    CUtil::GetDirectory(Name,strPath);
    CUtil::CreateDirectoryEx(strPath);
    m_File.OpenForWrite(Name,true,true);
    NewFile=true;
    HandleType=FILE_HANDLENORMAL;
    SkipClose=false;
    if (NameW!=NULL)
        strcpyw(FileNameW,NameW);
    else
        *FileNameW=0;
    if (Name!=NULL)
        strcpy(FileName,Name);
    else
        WideToChar(NameW,FileName);
    //AddFileToList(hFile);
    AddFileToList();
    //return(hFile!=BAD_HANDLE);
    return true;
}
Exemplo n.º 5
0
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
{
  const wchar *DestPtr=SrcPath;
  for (const wchar *s=DestPtr;*s!=0;s++)
    if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
      DestPtr=s+4;
  while (*DestPtr)
  {
    const wchar *s=DestPtr;
    if (s[0] && IsDriveDiv(s[1]))
      s+=2;
    if (s[0]=='\\' && s[1]=='\\')
    {
      const wchar *Slash=strchrw(s+2,'\\');
      if (Slash!=NULL && (Slash=strchrw(Slash+1,'\\'))!=NULL)
        s=Slash+1;
    }
    for (const wchar *t=s;*t!=0;t++)
      if (IsPathDiv(*t))
        s=t+1;
      else
        if (*t!='.')
          break;
    if (s==DestPtr)
      break;
    DestPtr=s;
  }
  if (DestPath!=NULL)
  {
    wchar TmpStr[NM];
    strncpyw(TmpStr,DestPtr,sizeof(TmpStr)/sizeof(TmpStr[0])-1);
    strcpyw(DestPath,TmpStr);
  }
  return((wchar *)DestPtr);
}
Exemplo n.º 6
0
void FindFile::SetMaskW(const wchar *FindMaskW)
{
  if (FindMaskW==NULL)
    return;
  strcpyw(FindFile::FindMaskW,FindMaskW);
  if (*FindMask==0)
    WideToChar(FindMaskW,FindMask);
  FirstCall=true;
}
Exemplo n.º 7
0
bool ScanTree::PrepareMasks()
{
    ScanEntireDisk=false;
    if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
        return(false);
    CurMask[ASIZE(CurMask)-1]=0;
    CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_32
    UnixSlashToDos(CurMask);
#endif

    // We wish to scan entire disk if mask like c:\ is specified
    // regardless of recursion mode. Use c:\*.* mask when need to scan only
    // the root directory.
    ScanEntireDisk=IsDiskLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;

    char *Name=PointToName(CurMask);
    if (*Name==0)
        strcat(CurMask,MASKALL);
    if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
    {
        AddEndSlash(CurMask);
        strcat(CurMask,MASKALL);
    }
    SpecPathLength=Name-CurMask;
//  if (SpecPathLength>1)
//    SpecPathLength--;

    bool WideName=(*CurMaskW!=0);

    if (WideName)
    {
        wchar *NameW=PointToName(CurMaskW);
        if (*NameW==0)
            strcatw(CurMaskW,MASKALLW);
        if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
        {
            AddEndSlash(CurMaskW);
            strcatw(CurMaskW,MASKALLW);
        }
        SpecPathLengthW=NameW-CurMaskW;
    }
    else
    {
        wchar WideMask[NM];
        CharToWide(CurMask,WideMask);
        SpecPathLengthW=PointToName(WideMask)-WideMask;
    }
    Depth=0;

    strcpy(OrigCurMask,CurMask);
    strcpyw(OrigCurMaskW,CurMaskW);

    return(true);
}
Exemplo n.º 8
0
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW)
{
  if (NameW!=NULL && *NameW!=0)
  {
    if (DestW!=NameW)
      strcpyw(DestW,NameW);
  }
  else
    CharToWide(Name,DestW);
  return(DestW);
}
Exemplo n.º 9
0
void ConvertNameToFull(const wchar *Src,wchar *Dest)
{
  if (Src==NULL || *Src==0)
  {
    *Dest=0;
    return;
  }
#ifdef _WIN_32
#ifndef _WIN_CE
  if (WinNT())
#endif
  {
//#ifndef _WIN_CE
#if !defined(_WIN_CE) && !defined(_LINUX)
    wchar FullName[NM],*NamePtr;
    if (GetFullPathNameW(Src,sizeof(FullName)/sizeof(FullName[0]),FullName,&NamePtr))
      strcpyw(Dest,FullName);
    else
#endif
      if (Src!=Dest)
        strcpyw(Dest,Src);
  }
#ifndef _WIN_CE
  else
  {
    char AnsiName[NM];
    WideToChar(Src,AnsiName);
    ConvertNameToFull(AnsiName,AnsiName);
    CharToWide(AnsiName,Dest);
  }
#endif
#else
  char AnsiName[NM];
  WideToChar(Src,AnsiName);
  ConvertNameToFull(AnsiName,AnsiName);
  CharToWide(AnsiName,Dest);
#endif
}
Exemplo n.º 10
0
bool ScanTree::PrepareMasks()
{
  if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
    return(false);
  CurMask[ASIZE(CurMask)-1]=0;
  CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_32
  UnixSlashToDos(CurMask);
#endif
  char *Name=PointToName(CurMask);
  if (*Name==0)
    strcat(CurMask,MASKALL);
  if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
  {
    AddEndSlash(CurMask);
    strcat(CurMask,MASKALL);
  }
  SpecPathLength=Name-CurMask;
//  if (SpecPathLength>1)
//    SpecPathLength--;

  bool WideName=(*CurMaskW!=0);

  if (WideName)
  {
    wchar *NameW=PointToName(CurMaskW);
    if (*NameW==0)
      strcatw(CurMaskW,MASKALLW);
    if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
    {
      AddEndSlash(CurMaskW);
      strcatw(CurMaskW,MASKALLW);
    }
    SpecPathLengthW=NameW-CurMaskW;
  }
  else
  {
    wchar WideMask[NM];
    CharToWide(CurMask,WideMask);
    SpecPathLengthW=PointToName(WideMask)-WideMask;
  }
  Depth=0;

  strcpy(OrigCurMask,CurMask);
  strcpyw(OrigCurMaskW,CurMaskW);

  return(true);
}
Exemplo n.º 11
0
bool File::Create(const char *Name,const wchar *NameW)
{
// Below commented code was left behind on spiffs request for possible later usage 
/*#ifdef _WIN_32
#ifndef _XBOX
  if (WinNT() && NameW!=NULL && *NameW!=0)
    hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                      CREATE_ALWAYS,0,NULL);
  else
#endif
    hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
                     CREATE_ALWAYS,0,NULL);
#else
  hFile=fopen(Name,CREATEBINARY);
#endif*/
  char name[NM];
  if (NameW)
    WideToUtf(NameW, name, NM);
  else
    strcpy(name, Name);
  char* lastslash = strrchr(name, '\\');
  char tmp;
  if (!lastslash)
    lastslash = strrchr(name, '/');
  if (lastslash) {
    tmp = *lastslash;
    *lastslash = '\0';
  }
  XBMC->CreateDirectory(name);
  *lastslash = tmp;
  m_File = XBMC->OpenFileForWrite(name, true);
  NewFile=true;
  HandleType=FILE_HANDLENORMAL;
  SkipClose=false;
  if (NameW!=NULL)
    strcpyw(FileNameW,NameW);
  else
    *FileNameW=0;
  if (Name!=NULL)
    strcpy(FileName,Name);
  else
    WideToChar(NameW,FileName);
  //AddFileToList(hFile);
  AddFileToList();
  //return(hFile!=BAD_HANDLE);
  return true;
}
Exemplo n.º 12
0
unsigned int StringList::AddString(const char *Str,const wchar *StrW)
{
  int PrevSize=StringData.Size();
  StringData.Add(strlen(Str)+1);
  strcpy(&StringData[PrevSize],Str);
  if (StrW!=NULL && *StrW!=0)
  {
    int PrevPos=PosDataW.Size();
    PosDataW.Add(1);
    PosDataW[PrevPos]=PrevSize;

    int PrevSizeW=StringDataW.Size();
    StringDataW.Add(strlenw(StrW)+1);
    strcpyw(&StringDataW[PrevSizeW],StrW);
  }
  StringsCount++;
  return(PrevSize);
}
Exemplo n.º 13
0
void SetExt(wchar *Name,const wchar *NewExt)
{
  if (Name==NULL || *Name==0)
    return;
  wchar *Dot=GetExt(Name);
  if (NewExt==NULL)
  {
    if (Dot!=NULL)
      *Dot=0;
  }
  else
    if (Dot==NULL)
    {
      strcatw(Name,L".");
      strcatw(Name,NewExt);
    }
    else
      strcpyw(Dot+1,NewExt);
}
Exemplo n.º 14
0
wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName,uint MaxLength)
{
  if (DestName!=NULL && DestName!=SrcName)
    if (strlenw(SrcName)>=MaxLength)
    {
      *DestName=0;
      return(DestName);
    }
    else
      strcpyw(DestName,SrcName);
  for (wchar *s=SrcName;*s!=0;s++)
  {
    if (*s=='/')
      if (DestName==NULL)
        *s='\\';
      else
        DestName[s-SrcName]='\\';
  }
  return(DestName==NULL ? SrcName:DestName);
}
Exemplo n.º 15
0
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);
  }

  // archive with corrupt encrypted header can be closed in IsArchive() call
  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)!=0);

    // If several volume names from same volume set are specified
    // and current volume is not first in set and first volume is present
    // and specified too, let's skip the current volume.
    if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
        Cmd->ArcNames->Search(FirstVolName,NULL,false))
      return(EXTRACT_ARC_NEXT);
  }
#endif

  int64 VolumeSetSize=0; // Total size of volumes after the current volume.

  if (Arc.Volume)
  {
    // Calculate the total size of all accessible volumes.
    // This size is necessary to display the correct total progress indicator.

    char NextName[NM];
    wchar NextNameW[NM];

    strcpy(NextName,Arc.FileName);
    strcpyw(NextNameW,Arc.FileNameW);

    while (true)
    {
      // First volume is already added to DataIO.TotalArcSize 
      // in initial TotalArcSize calculation in DoExtract.
      // So we skip it and start from second volume.
      NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
      struct FindData FD;
      if (FindFile::FastFind(NextName,NextNameW,&FD))
        VolumeSetSize+=FD.Size;
      else
        break;
    }
    DataIO.TotalArcSize+=VolumeSetSize;
  }

  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();

  // RAR can close a corrupt encrypted archive
  if (!Arc.IsOpened())
    return(EXTRACT_ARC_NEXT);


  while (1)
  {
    size_t Size=Arc.ReadHeader();
    bool Repeat=false;
    if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
      if (Repeat)
      {
        // If we started extraction from not first volume and need to
        // restart it from first, we must correct DataIO.TotalArcSize
        // for correct total progress display. We subtract the size
        // of current volume and all volumes after it and add the size
        // of new (first) volume.
        struct FindData OldArc,NewArc;
        if (FindFile::FastFind(Arc.FileName,Arc.FileNameW,&OldArc) &&
            FindFile::FastFind(ArcName,ArcNameW,&NewArc))
          DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
        return(EXTRACT_ARC_REPEAT);
      }
      else
        break;
  }

  return(EXTRACT_ARC_NEXT);
}
Exemplo n.º 16
0
HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd)
{
#ifndef _WIN_CE
  if (WinNT())
#endif
  {
    wchar WideMask[NM];
    if (MaskW!=NULL && *MaskW!=0)
      strcpyw(WideMask,MaskW);
    else
      CharToWide(Mask,WideMask);

    WIN32_FIND_DATAW FindData;
    if (hFind==INVALID_HANDLE_VALUE)
    {
      hFind=FindFirstFileW(WideMask,&FindData);
      if (hFind==INVALID_HANDLE_VALUE)
      {
        int SysErr=GetLastError();
        fd->Error=(SysErr!=ERROR_FILE_NOT_FOUND &&
                   SysErr!=ERROR_PATH_NOT_FOUND &&
                   SysErr!=ERROR_NO_MORE_FILES);
      }
    }
    else
      if (!FindNextFileW(hFind,&FindData))
      {
        hFind=INVALID_HANDLE_VALUE;
        fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
      }

    if (hFind!=INVALID_HANDLE_VALUE)
    {
      strcpyw(fd->NameW,WideMask);
      strcpyw(PointToName(fd->NameW),FindData.cFileName);
      WideToChar(fd->NameW,fd->Name);
      fd->Size=int32to64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
      fd->FileAttr=FindData.dwFileAttributes;
      WideToChar(FindData.cAlternateFileName,fd->ShortName);
      fd->ftCreationTime=FindData.ftCreationTime;
      fd->ftLastAccessTime=FindData.ftLastAccessTime;
      fd->ftLastWriteTime=FindData.ftLastWriteTime;
      fd->mtime=FindData.ftLastWriteTime;
      fd->ctime=FindData.ftCreationTime;
      fd->atime=FindData.ftLastAccessTime;
      fd->FileTime=fd->mtime.GetDos();

#ifndef _WIN_CE
      if (LowAscii(fd->NameW))
        *fd->NameW=0;
#endif
    }
  }
#ifndef _WIN_CE
  else
  {
    char CharMask[NM];
    if (Mask!=NULL && *Mask!=0)
      strcpy(CharMask,Mask);
    else
      WideToChar(MaskW,CharMask);

    WIN32_FIND_DATA FindData;
    if (hFind==INVALID_HANDLE_VALUE)
    {
      hFind=FindFirstFile(CharMask,&FindData);
      if (hFind==INVALID_HANDLE_VALUE)
      {
        int SysErr=GetLastError();
        fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && SysErr!=ERROR_PATH_NOT_FOUND;
      }
    }
    else
      if (!FindNextFile(hFind,&FindData))
      {
        hFind=INVALID_HANDLE_VALUE;
        fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
      }

    if (hFind!=INVALID_HANDLE_VALUE)
    {
      strcpy(fd->Name,CharMask);
      strcpy(PointToName(fd->Name),FindData.cFileName);
      CharToWide(fd->Name,fd->NameW);
      fd->Size=int32to64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
      fd->FileAttr=FindData.dwFileAttributes;
      strcpy(fd->ShortName,FindData.cAlternateFileName);
      fd->ftCreationTime=FindData.ftCreationTime;
      fd->ftLastAccessTime=FindData.ftLastAccessTime;
      fd->ftLastWriteTime=FindData.ftLastWriteTime;
      fd->mtime=FindData.ftLastWriteTime;
      fd->ctime=FindData.ftCreationTime;
      fd->atime=FindData.ftLastAccessTime;
      fd->FileTime=fd->mtime.GetDos();
      if (LowAscii(fd->Name))
        *fd->NameW=0;
    }
  }
#endif
  fd->Flags=0;
  return(hFind);
}
Exemplo n.º 17
0
void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
{

  switch(etoupper(Switch[0]))
  {
    case 'I':
      if (strnicomp(&Switch[1],"LOG",3)==0)
      {
        strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
        break;
      }
      if (stricomp(&Switch[1],"SND")==0)
      {
        Sound=true;
        break;
      }
      if (stricomp(&Switch[1],"ERR")==0)
      {
        MsgStream=MSG_STDERR;
        break;
      }
      if (strnicomp(&Switch[1],"EML",3)==0)
      {
        strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
        EmailTo[sizeof(EmailTo)-1]=0;
        break;
      }
      if (stricomp(&Switch[1],"NUL")==0)
      {
        MsgStream=MSG_NULL;
        break;
      }
      if (etoupper(Switch[1])=='D')
      {
        for (int I=2;Switch[I]!=0;I++)
          switch(etoupper(Switch[I]))
          {
            case 'Q':
              MsgStream=MSG_ERRONLY;
              break;
            case 'C':
              DisableCopyright=true;
              break;
            case 'D':
              DisableDone=true;
              break;
            case 'P':
              DisablePercentage=true;
              break;
          }
        break;
      }
      if (stricomp(&Switch[1],"OFF")==0)
      {
        Shutdown=true;
        break;
      }
      break;
    case 'T':
      switch(etoupper(Switch[1]))
      {
        case 'K':
          ArcTime=ARCTIME_KEEP;
          break;
        case 'L':
          ArcTime=ARCTIME_LATEST;
          break;
        case 'O':
          FileTimeBefore.SetAgeText(Switch+2);
          break;
        case 'N':
          FileTimeAfter.SetAgeText(Switch+2);
          break;
        case 'B':
          FileTimeBefore.SetIsoText(Switch+2);
          break;
        case 'A':
          FileTimeAfter.SetIsoText(Switch+2);
          break;
        case 'S':
          {
            EXTTIME_MODE Mode=EXTTIME_HIGH3;
            bool CommonMode=Switch[2]>='0' && Switch[2]<='4';
            if (CommonMode)
              Mode=(EXTTIME_MODE)(Switch[2]-'0');
            if (Switch[2]=='-')
              Mode=EXTTIME_NONE;
            if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0)
              xmtime=xctime=xatime=Mode;
            else
            {
              if (Switch[3]>='0' && Switch[3]<='4')
                Mode=(EXTTIME_MODE)(Switch[3]-'0');
              if (Switch[3]=='-')
                Mode=EXTTIME_NONE;
              switch(etoupper(Switch[2]))
              {
                case 'M':
                  xmtime=Mode;
                  break;
                case 'C':
                  xctime=Mode;
                  break;
                case 'A':
                  xatime=Mode;
                  break;
                case 'R':
                  xarctime=Mode;
                  break;
              }
            }
          }
          break;
        case '-':
          Test=false;
          break;
        case 0:
          Test=true;
          break;
        default:
          BadSwitch(Switch);
          break;
      }
      break;
    case 'A':
      switch(etoupper(Switch[1]))
      {
        case 'C':
          ClearArc=true;
          break;
        case 'D':
          AppendArcNameToPath=true;
          break;
        case 'G':
          if (Switch[2]=='-' && Switch[3]==0)
            GenerateArcName=0;
          else
          {
            GenerateArcName=true;
            strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
          }
          break;
        case 'N': //reserved for archive name
          break;
        case 'O':
          AddArcOnly=true;
          break;
        case 'P':
          strcpy(ArcPath,Switch+2);
          if (SwitchW!=NULL && *SwitchW!=0)
            strcpyw(ArcPathW,SwitchW+2);
          break;
        case 'S':
          SyncFiles=true;
          break;
        default:
          BadSwitch(Switch);
          break;
      }
      break;
    case 'D':
      if (Switch[2]==0)
        switch(etoupper(Switch[1]))
        {
          case 'S':
            DisableSortSolid=true;
            break;
          case 'H':
            OpenShared=true;
            break;
          case 'F':
            DeleteFiles=true;
            break;
        }
      break;
    case 'O':
      switch(etoupper(Switch[1]))
      {
        case '+':
          Overwrite=OVERWRITE_ALL;
          break;
        case '-':
          Overwrite=OVERWRITE_NONE;
          break;
        case 0:
          Overwrite=OVERWRITE_FORCE_ASK;
          break;
        case 'R':
          Overwrite=OVERWRITE_AUTORENAME;
          break;
        case 'W':
          ProcessOwners=true;
          break;
#ifdef SAVE_LINKS
        case 'L':
          SaveLinks=true;
          break;
#endif
#ifdef _WIN_32
        case 'S':
          SaveStreams=true;
          break;
        case 'C':
          SetCompressedAttr=true;
          break;
#endif
        default :
          BadSwitch(Switch);
          break;
      }
      break;
    case 'R':
      switch(etoupper(Switch[1]))
      {
        case 0:
          Recurse=RECURSE_ALWAYS;
          break;
        case '-':
          Recurse=0;
          break;
        case '0':
          Recurse=RECURSE_WILDCARDS;
          break;
#ifndef _WIN_CE
        case 'I':
          {
            Priority=atoi(Switch+2);
            char *ChPtr=strchr(Switch+2,':');
            if (ChPtr!=NULL)
            {
              SleepTime=atoi(ChPtr+1);
              InitSystemOptions(SleepTime);
            }
            SetPriority(Priority);
          }
          break;
#endif
      }
      break;
    case 'Y':
      AllYes=true;
      break;
    case 'N':
    case 'X':
      if (Switch[1]!=0)
      {
        StringList *Args=etoupper(Switch[0])=='N' ? InclArgs:ExclArgs;
        if (Switch[1]=='@' && !IsWildcard(Switch))
        {
          RAR_CHARSET Charset=FilelistCharset;

#if defined(_WIN_32) && !defined(GUI)
          // for compatibility reasons we use OEM encoding
          // in Win32 console version by default

          if (Charset==RCH_DEFAULT)
            Charset=RCH_OEM;
#endif

          ReadTextFile(Switch+2,Args,false,true,Charset,true,true,true);
        }
        else
          Args->AddString(Switch+1);
      }
      break;
    case 'E':
      switch(etoupper(Switch[1]))
      {
        case 'P':
          switch(Switch[2])
          {
            case 0:
              ExclPath=EXCL_SKIPWHOLEPATH;
              break;
            case '1':
              ExclPath=EXCL_BASEPATH;
              break;
            case '2':
              ExclPath=EXCL_SAVEFULLPATH;
              break;
            case '3':
              ExclPath=EXCL_ABSPATH;
              break;
          }
          break;
        case 'D':
          ExclEmptyDir=true;
          break;
        case 'E':
          ProcessEA=false;
          break;
        case 'N':
          NoEndBlock=true;
          break;
        default:
          if (Switch[1]=='+')
          {
            InclFileAttr=GetExclAttr(&Switch[2]);
            InclAttrSet=true;
          }
          else
            ExclFileAttr=GetExclAttr(&Switch[1]);
          break;
      }
      break;
    case 'P':
      if (Switch[1]==0)
      {
        GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password));
        eprintf("\n");
      }
      else
        strncpyz(Password,Switch+1,ASIZE(Password));
      break;
    case 'H':
      if (etoupper(Switch[1])=='P')
      {
        EncryptHeaders=true;
        if (Switch[2]!=0)
          strncpyz(Password,Switch+2,ASIZE(Password));
        else
          if (*Password==0)
          {
            GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password));
            eprintf("\n");
          }
      }
      break;
    case 'Z':
      strncpyz(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",ASIZE(CommentFile));
      break;
    case 'M':
      switch(etoupper(Switch[1]))
      {
        case 'C':
          {
            char *Str=Switch+2;
            if (*Str=='-')
              for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++)
                FilterModes[I].State=FILTER_DISABLE;
            else
              while (*Str)
              {
                int Param1=0,Param2=0;
                FilterState State=FILTER_AUTO;
                FilterType Type=FILTER_NONE;
                if (isdigit(*Str))
                {
                  Param1=atoi(Str);
                  while (isdigit(*Str))
                    Str++;
                }
                if (*Str==':' && isdigit(Str[1]))
                {
                  Param2=atoi(++Str);
                  while (isdigit(*Str))
                    Str++;
                }
                switch(etoupper(*(Str++)))
                {
                  case 'T': Type=FILTER_PPM;         break;
                  case 'E': Type=FILTER_E8;          break;
                  case 'D': Type=FILTER_DELTA;       break;
                  case 'A': Type=FILTER_AUDIO;       break;
                  case 'C': Type=FILTER_RGB;         break;
                  case 'I': Type=FILTER_ITANIUM;     break;
                  case 'L': Type=FILTER_UPCASETOLOW; break;
                }
                if (*Str=='+' || *Str=='-')
                  State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE;
                FilterModes[Type].State=State;
                FilterModes[Type].Param1=Param1;
                FilterModes[Type].Param2=Param2;
              }
            }
          break;
        case 'M':
          break;
        case 'D':
          {
            if ((WinSize=atoi(&Switch[2]))==0)
              WinSize=0x10000<<(etoupper(Switch[2])-'A');
            else
              WinSize*=1024;
            if (!CheckWinSize())
              BadSwitch(Switch);
          }
          break;
        case 'S':
          {
            char *Names=Switch+2,DefNames[512];
            if (*Names==0)
            {
              strcpy(DefNames,DefaultStoreList);
              Names=DefNames;
            }
            while (*Names!=0)
            {
              char *End=strchr(Names,';');
              if (End!=NULL)
                *End=0;
              if (*Names=='.')
                Names++;
              char Mask[NM];
              if (strpbrk(Names,"*?.")==NULL)
                sprintf(Mask,"*.%s",Names);
              else
                strcpy(Mask,Names);
              StoreArgs->AddString(Mask);
              if (End==NULL)
                break;
              Names=End+1;
            }
          }
          break;
#ifdef PACK_SMP
        case 'T':
          Threads=atoi(Switch+2);
          if (Threads>MaxSearchThreads)
            BadSwitch(Switch);
          else
          {
          }
          break;
#endif
        default:
          Method=Switch[1]-'0';
          if (Method>5 || Method<0)
            BadSwitch(Switch);
          break;
      }
      break;
    case 'V':
      switch(etoupper(Switch[1]))
      {
#ifdef _WIN_32
        case 'D':
          EraseDisk=true;
          break;
#endif
        case 'N':
          OldNumbering=true;
          break;
        case 'P':
          VolumePause=true;
          break;
        case 'E':
          if (etoupper(Switch[2])=='R')
            VersionControl=atoi(Switch+3)+1;
          break;
        case '-':
          VolSize=0;
          break;
        default:
          {
            Int64 NewVolSize=atoil(&Switch[1]);

            if (NewVolSize==0)
              NewVolSize=INT64ERR;
            else
              switch (Switch[strlen(Switch)-1])
              {
                case 'f':
                case 'F':
                  switch(int64to32(NewVolSize))
                  {
                    case 360:
                      NewVolSize=362496;
                      break;
                    case 720:
                      NewVolSize=730112;
                      break;
                    case 1200:
                      NewVolSize=1213952;
                      break;
                    case 1440:
                      NewVolSize=1457664;
                      break;
                    case 2880:
                      NewVolSize=2915328;
                      break;
                  }
                  break;
                case 'k':
                  NewVolSize*=1024;
                  break;
                case 'm':
                  NewVolSize*=1024*1024;
                  break;
                case 'M':
                  NewVolSize*=1000*1000;
                  break;
                case 'g':
                  NewVolSize*=1024*1024;
                  NewVolSize*=1024;
                  break;
                case 'G':
                  NewVolSize*=1000*1000;
                  NewVolSize*=1000;
                  break;
                case 'b':
                case 'B':
                  break;
                default:
                  NewVolSize*=1000;
                  break;
              }
            if (VolSize==0)
              VolSize=NewVolSize;
            else
              NextVolSizes.Push(NewVolSize);
          }
          break;
      }
      break;
    case 'F':
      if (Switch[1]==0)
        FreshFiles=true;
      else
        BadSwitch(Switch);
      break;
    case 'U':
      if (Switch[1]==0)
        UpdateFiles=true;
      else
        BadSwitch(Switch);
      break;
    case 'W':
      strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
      AddEndSlash(TempPath);
      break;
    case 'S':
      if (strnicomp(Switch,"SFX",3)==0)
      {
        const char *SFXName=Switch[3] ? Switch+3:DefSFXName;
        if (PointToName(SFXName)!=SFXName || FileExist(SFXName))
          strcpy(SFXModule,SFXName);
        else
          GetConfigName(SFXName,SFXModule,true);
      }
      if (isdigit(Switch[1]))
      {
        Solid|=SOLID_COUNT;
        SolidCount=atoi(&Switch[1]);
      }
      else
        switch(etoupper(Switch[1]))
        {
          case 0:
            Solid|=SOLID_NORMAL;
            break;
          case '-':
            Solid=SOLID_NONE;
            break;
          case 'E':
            Solid|=SOLID_FILEEXT;
            break;
          case 'V':
            Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT;
            break;
          case 'D':
            Solid|=SOLID_VOLUME_DEPENDENT;
            break;
          case 'L':
            if (isdigit(Switch[2]))
              FileSizeLess=atoil(Switch+2);
            break;
          case 'M':
            if (isdigit(Switch[2]))
              FileSizeMore=atoil(Switch+2);
            break;
          case 'C':
            {
              RAR_CHARSET rch=RCH_DEFAULT;
              switch(etoupper(Switch[2]))
              {
                case 'A':
                  rch=RCH_ANSI;
                  break;
                case 'O':
                  rch=RCH_OEM;
                  break;
                case 'U':
                  rch=RCH_UNICODE;
                  break;
                default :
                  BadSwitch(Switch);
                  break;
              };
              if (Switch[3]==0)
                CommentCharset=FilelistCharset=rch;
              else
                for (int I=3;Switch[I]!=0;I++)
                  switch(etoupper(Switch[I]))
                  {
                    case 'C':
                      CommentCharset=rch;
                      break;
                    case 'L':
                      FilelistCharset=rch;
                      break;
                    default:
                      BadSwitch(Switch);
                      break;
                  }
            }
            break;

        }
      break;
    case 'C':
      if (Switch[2]==0)
        switch(etoupper(Switch[1]))
        {
          case '-':
            DisableComment=true;
            break;
          case 'U':
            ConvertNames=NAMES_UPPERCASE;
            break;
          case 'L':
            ConvertNames=NAMES_LOWERCASE;
            break;
        }
      break;
    case 'K':
      switch(etoupper(Switch[1]))
      {
        case 'B':
          KeepBroken=true;
          break;
        case 0:
          Lock=true;
          break;
      }
      break;
#ifndef GUI
    case '?' :
      OutHelp();
      break;
#endif
    default :
      BadSwitch(Switch);
      break;
  }
}
Exemplo n.º 18
0
bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
{
    /*ErrorType=FILE_SUCCESS;
    FileHandle hNewFile;
    if (File::OpenShared)
      OpenShared=true;
    #ifdef _WIN_32
    uint Access=GENERIC_READ;
    if (Update)
      Access|=GENERIC_WRITE;
    uint ShareMode=FILE_SHARE_READ;
    if (OpenShared)
      ShareMode|=FILE_SHARE_WRITE;
    #ifndef _XBOX
    if (WinNT() && NameW!=NULL && *NameW!=0)
      hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,
                           FILE_FLAG_SEQUENTIAL_SCAN,NULL);
    else
    #endif
      hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,
                          FILE_FLAG_SEQUENTIAL_SCAN,NULL);

    if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
      ErrorType=FILE_NOTFOUND;
    #else
    int flags=Update ? O_RDWR:O_RDONLY;
    #ifdef O_BINARY
    flags|=O_BINARY;
    #if defined(_AIX) && defined(_LARGE_FILE_API)
    flags|=O_LARGEFILE;
    #endif
    #endif
    #if defined(_EMX) && !defined(_DJGPP)
    int sflags=OpenShared ? SH_DENYNO:SH_DENYWR;
    int handle=sopen(Name,flags,sflags);
    #else
    int handle=open(Name,flags);
    #ifdef LOCK_EX
    if (!OpenShared && Update && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
    {
      close(handle);
      return(false);
    }
    #endif
    #endif
    hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY);
    if (hNewFile==BAD_HANDLE && errno==ENOENT)
      ErrorType=FILE_NOTFOUND;
    #endif
    NewFile=false;
    HandleType=FILE_HANDLENORMAL;
    SkipClose=false;
    bool success=hNewFile!=BAD_HANDLE;*/
    bool success;
    if (Update)
        success = m_File.OpenForWrite(Name);
    else
        success = m_File.Open(Name);
    if (success)
    {
//    hFile=hNewFile;
        if (NameW!=NULL)
            strcpyw(FileNameW,NameW);
        else
            *FileNameW=0;
        if (Name!=NULL)
            strcpy(FileName,Name);
        else
            WideToChar(NameW,FileName);
        //AddFileToList(hFile);
        AddFileToList();
    }
    return(success);
}
Exemplo n.º 19
0
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Command)
{
  RAROptions *Cmd=Arc.GetRAROptions();

  int HeaderType=Arc.GetHeaderType();
  FileHeader *hd=HeaderType==NEWSUB_HEAD ? &Arc.SubHead:&Arc.NewLhd;
  bool SplitHeader=(HeaderType==FILE_HEAD || HeaderType==NEWSUB_HEAD) &&
                   (hd->Flags & LHD_SPLIT_AFTER)!=0;

  if (DataIO!=NULL && SplitHeader && hd->UnpVer>=20 &&
      hd->FileCRC!=0xffffffff && DataIO->PackedCRC!=~hd->FileCRC)
  {
    Log(Arc.FileName,St(MDataBadCRC),hd->FileName,Arc.FileName);
  }

  Int64 PosBeforeClose=Arc.Tell();
  Arc.Close();

  char NextName[NM];
  wchar NextNameW[NM];
  *NextNameW=0;
  strcpy(NextName,Arc.FileName);
  NextVolumeName(NextName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);

  if (*Arc.FileNameW!=0)
  {
    // Copy incremented trailing low ASCII volume name part to Unicode name.
    // It is simpler than also implementing Unicode version of NextVolumeName.

    strcpyw(NextNameW,Arc.FileNameW);
    char *NumPtr=GetVolNumPart(NextName);

    // moving to first digit in volume number
    while (NumPtr>NextName && isdigit(*NumPtr) && isdigit(*(NumPtr-1)))
      NumPtr--;

    // also copy the first character before volume number,
    // because it can be changed when going from .r99 to .s00
    if (NumPtr>NextName)
      NumPtr--;

    int CharsToCopy=strlen(NextName)-(NumPtr-NextName);
    int DestPos=strlenw(NextNameW)-CharsToCopy;
    if (DestPos>0)
    {
      CharToWide(NumPtr,NextNameW+DestPos,ASIZE(NextNameW)-DestPos-1);
      NextNameW[ASIZE(NextNameW)-1]=0;
    }
  }

#if !defined(SFX_MODULE) && !defined(RARDLL)
  bool RecoveryDone=false;
#endif
  bool FailedOpen=false,OldSchemeTested=false;

  while (!Arc.Open(NextName,NextNameW))
  {
    if (!OldSchemeTested)
    {
      char AltNextName[NM];
      strcpy(AltNextName,Arc.FileName);
      NextVolumeName(AltNextName,true);
      OldSchemeTested=true;
      if (Arc.Open(AltNextName))
      {
        strcpy(NextName,AltNextName);
        *NextNameW=0;
        break;
      }
    }
#ifdef RARDLL
    if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
        Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_ASK)==-1)
    {
      Cmd->DllError=ERAR_EOPEN;
      FailedOpen=true;
      break;
    }
    if (Cmd->ChangeVolProc!=NULL)
    {
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
      _EBX=_ESP;
#endif
      int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
      _ESP=_EBX;
#endif
      if (RetCode==0)
      {
        Cmd->DllError=ERAR_EOPEN;
        FailedOpen=true;
        break;
      }
    }
#else // RARDLL

#if !defined(SFX_MODULE) && !defined(_WIN_CE)
    if (!RecoveryDone)
    {
      RecVolumes RecVol;
      RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
      RecoveryDone=true;
      continue;
    }
#endif

#ifndef GUI
    if (!Cmd->VolumePause && !IsRemovable(NextName))
    {
      FailedOpen=true;
      break;
    }
#endif
#ifndef SILENT
    if (Cmd->AllYes || !AskNextVol(NextName))
#endif
    {
      FailedOpen=true;
      break;
    }
#endif // RARDLL
    *NextNameW=0;
  }
  if (FailedOpen)
  {
#if !defined(SILENT) && !defined(_WIN_CE)
      Log(Arc.FileName,St(MAbsNextVol),NextName);
#endif
    Arc.Open(Arc.FileName,Arc.FileNameW);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return(false);
  }
  Arc.CheckArc(true);
#ifdef RARDLL
  if (Cmd->Callback!=NULL &&
      Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_NOTIFY)==-1)
    return(false);
  if (Cmd->ChangeVolProc!=NULL)
  {
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _EBX=_ESP;
#endif
    int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _ESP=_EBX;
#endif
    if (RetCode==0)
      return(false);
  }
#endif

  if (Command=='T' || Command=='X' || Command=='E')
    mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
  if (SplitHeader)
    Arc.SearchBlock(HeaderType);
  else
    Arc.ReadHeader();
  if (Arc.GetHeaderType()==FILE_HEAD)
  {
    Arc.ConvertAttributes();
    Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
  }
#ifndef GUI
  if (ShowFileName)
  {
    char OutName[NM];
    IntToExt(Arc.NewLhd.FileName,OutName);
#ifdef UNICODE_SUPPORTED
    bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
    if (WideName)
    {
      wchar NameW[NM];
      ConvertPath(Arc.NewLhd.FileNameW,NameW);
      char Name[NM];
      if (WideToChar(NameW,Name) && IsNameUsable(Name))
        strcpy(OutName,Name);
    }
#endif
    mprintf(St(MExtrPoints),OutName);
    if (!Cmd->DisablePercentage)
      mprintf("     ");
  }
#endif
  if (DataIO!=NULL)
  {
    if (HeaderType==ENDARC_HEAD)
      DataIO->UnpVolume=false;
    else
    {
      DataIO->UnpVolume=(hd->Flags & LHD_SPLIT_AFTER);
      DataIO->SetPackedSizeToRead(hd->FullPackSize);
    }
#ifdef SFX_MODULE
    DataIO->UnpArcSize=Arc.FileLength();
    DataIO->CurUnpRead=0;
#endif
    DataIO->PackedCRC=0xffffffff;
//    DataIO->SetFiles(&Arc,NULL);
  }
  return(true);
}
Exemplo n.º 20
0
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
                         const wchar *NameW,bool Silent)
{
  char ArcName[NM];
  wchar ArcNameW[NM];
  strcpy(ArcName,Name);
  strcpyw(ArcNameW,NameW);
  char *Ext=GetExt(ArcName);
  bool NewStyle=false;
  bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0;
  if (RevName)
  {
    for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--)
      if (!isdigit(*Ext))
      {
        if (isdigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2))
          DigitGroup++;
        else if (DigitGroup<2)
        {
          NewStyle=true;
          break;
        }
      }
    while (isdigit(*Ext) && Ext>ArcName+1)
      Ext--;
    strcpy(Ext,"*.*");
    FindFile Find;
    Find.SetMask(ArcName);
    struct FindData FD;
    while (Find.Next(&FD))
    {
      Archive Arc(Cmd);
      if (Arc.WOpen(FD.Name,FD.NameW) && Arc.IsArchive(true))
      {
        strcpy(ArcName,FD.Name);
        *ArcNameW=0;
        break;
      }
    }
  }

  Archive Arc(Cmd);
  if (!Arc.WCheckOpen(ArcName,ArcNameW))
    return(false);
  if (!Arc.Volume)
  {
#ifndef SILENT
    Log(ArcName,St(MNotVolume),ArcName);
#endif
    return(false);
  }
  bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING);
  Arc.Close();
  char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
  char RecVolMask[NM];
  strcpy(RecVolMask,ArcName);
  int BaseNamePartLength=VolNumStart-ArcName;
  strcpy(RecVolMask+BaseNamePartLength,"*.rev");

#ifndef SILENT
  Int64 RecFileSize=0;
#endif
  FindFile Find;
  Find.SetMask(RecVolMask);
  struct FindData RecData;
  int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
  char PrevName[NM];
  while (Find.Next(&RecData))
  {
    char *Name=RecData.Name;
    int P[3];
    if (!RevName && !NewStyle)
    {
      NewStyle=true;
      char *Dot=GetExt(Name);
      if (Dot!=NULL)
      {
        int LineCount=0;
        Dot--;
        while (Dot>Name && *Dot!='.')
        {
          if (*Dot=='_')
            LineCount++;
          Dot--;
        }
        if (LineCount==2)
          NewStyle=false;
      }
    }
    if (NewStyle)
    {
      File CurFile;
      CurFile.TOpen(Name);
      CurFile.Seek(0,SEEK_END);
      Int64 Length=CurFile.Tell();
      CurFile.Seek(Length-7,SEEK_SET);
      for (int I=0;I<3;I++)
        P[2-I]=CurFile.GetByte()+1;
      uint FileCRC=0;
      for (int I=0;I<4;I++)
        FileCRC|=CurFile.GetByte()<<(I*8);
      if (FileCRC!=CalcFileCRC(&CurFile,Length-4))
      {
#ifndef SILENT
        mprintf(St(MCRCFailed),Name);
#endif
        continue;
      }
    }
    else
    {
      char *Dot=GetExt(Name);
      if (Dot==NULL)
        continue;
      bool WrongParam=false;
      for (unsigned int I=0;I<sizeof(P)/sizeof(P[0]);I++)
      {
        do
        {
          Dot--;
        } while (isdigit(*Dot) && Dot>=Name+BaseNamePartLength);
        P[I]=atoi(Dot+1);
        if (P[I]==0 || P[I]>255)
          WrongParam=true;
      }
      if (WrongParam)
        continue;
    }
    if (P[1]+P[2]>255)
      continue;
    if ((RecVolNumber!=0 && RecVolNumber!=P[1]) || (FileNumber!=0 && FileNumber!=P[2]))
    {
#ifndef SILENT
      Log(NULL,St(MRecVolDiffSets),Name,PrevName);
#endif
      return(false);
    }
    RecVolNumber=P[1];
    FileNumber=P[2];
    strcpy(PrevName,Name);
    File *NewFile=new File;
    NewFile->TOpen(Name);
    SrcFile[FileNumber+P[0]-1]=NewFile;
    FoundRecVolumes++;
#ifndef SILENT
    if (RecFileSize==0)
      RecFileSize=NewFile->FileLength();
#endif
  }
#ifndef SILENT
  if (!Silent || FoundRecVolumes!=0)
  {
    mprintf(St(MRecVolFound),FoundRecVolumes);
  }
#endif
  if (FoundRecVolumes==0)
    return(false);

  bool WriteFlags[256];
  memset(WriteFlags,0,sizeof(WriteFlags));

  char LastVolName[NM];
  *LastVolName=0;

  for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
  {
    Archive *NewFile=new Archive;
    bool ValidVolume=FileExist(ArcName);
    if (ValidVolume)
    {
      NewFile->TOpen(ArcName);
      ValidVolume=NewFile->IsArchive(false);
      if (ValidVolume)
      {
        bool EndFound=false,EndBlockRequired=false;
        while (!EndFound && NewFile->ReadHeader()!=0)
        {
          if (NewFile->GetHeaderType()==FILE_HEAD)
          {
            if (NewFile->NewLhd.UnpVer>=29)
              EndBlockRequired=true;
            if (!EndBlockRequired && (NewFile->NewLhd.Flags & LHD_SPLIT_AFTER))
              EndFound=true;
          }
          if (NewFile->GetHeaderType()==ENDARC_HEAD)
          {
            if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 && 
                NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
            {
              ValidVolume=false;
#ifndef SILENT
              mprintf(St(MCRCFailed),ArcName);
#endif
            }
            EndFound=true;
          }
          NewFile->SeekToNext();
        }
        if (!EndFound)
          ValidVolume=false;
      }
      if (!ValidVolume)
      {
        NewFile->Close();
        char NewName[NM];
        strcpy(NewName,ArcName);
        strcat(NewName,".bad");
#ifndef SILENT
        mprintf(St(MBadArc),ArcName);
        mprintf(St(MRenaming),ArcName,NewName);
#endif
        rename(ArcName,NewName);
      }
      NewFile->Seek(0,SEEK_SET);
    }
    if (!ValidVolume)
    {
      NewFile->TCreate(ArcName);
      WriteFlags[CurArcNum]=true;
      MissingVolumes++;

      if (CurArcNum==FileNumber-1)
        strcpy(LastVolName,ArcName);

#ifndef SILENT
      mprintf(St(MAbsNextVol),ArcName);
#endif
    }
    SrcFile[CurArcNum]=(File*)NewFile;
    NextVolumeName(ArcName,!NewNumbering);
  }

#ifndef SILENT
  mprintf(St(MRecVolMissing),MissingVolumes);
#endif

  if (MissingVolumes==0)
  {
#ifndef SILENT
    mprintf(St(MRecVolAllExist));
#endif
    return(false);
  }

  if (MissingVolumes>FoundRecVolumes)
  {
#ifndef SILENT
    mprintf(St(MRecVolCannotFix));
#endif
    return(false);
  }
#ifndef SILENT
  mprintf(St(MReconstructing));
#endif

  RSCoder RSC(RecVolNumber);

  int TotalFiles=FileNumber+RecVolNumber;
  int Erasures[256],EraSize=0;

  for (int I=0;I<TotalFiles;I++)
    if (WriteFlags[I] || SrcFile[I]==NULL)
      Erasures[EraSize++]=I;

#ifndef SILENT
  Int64 ProcessedSize=0;
#ifndef GUI
  int LastPercent=-1;
  mprintf("     ");
#endif
#endif
  int RecCount=0;

  while (true)
  {
    if ((++RecCount & 15)==0)
      Wait();
    int MaxRead=0;
    for (int I=0;I<TotalFiles;I++)
      if (WriteFlags[I] || SrcFile[I]==NULL)
        memset(&Buf[I*RECVOL_BUFSIZE],0,RECVOL_BUFSIZE);
      else
      {
        int ReadSize=SrcFile[I]->Read(&Buf[I*RECVOL_BUFSIZE],RECVOL_BUFSIZE);
        if (ReadSize!=RECVOL_BUFSIZE)
          memset(&Buf[I*RECVOL_BUFSIZE+ReadSize],0,RECVOL_BUFSIZE-ReadSize);
        if (ReadSize>MaxRead)
          MaxRead=ReadSize;
      }
    if (MaxRead==0)
      break;
#ifndef SILENT
    int CurPercent=ToPercent(ProcessedSize,RecFileSize);
    if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
    {
      mprintf("\b\b\b\b%3d%%",CurPercent);
      LastPercent=CurPercent;
    }
    ProcessedSize+=MaxRead;
#endif
    for (int BufPos=0;BufPos<MaxRead;BufPos++)
    {
      byte Data[256];
      for (int I=0;I<TotalFiles;I++)
        Data[I]=Buf[I*RECVOL_BUFSIZE+BufPos];
      RSC.Decode(Data,TotalFiles,Erasures,EraSize);
      for (int I=0;I<EraSize;I++)
        Buf[Erasures[I]*RECVOL_BUFSIZE+BufPos]=Data[Erasures[I]];
/*
      for (int I=0;I<FileNumber;I++)
        Buf[I*RECVOL_BUFSIZE+BufPos]=Data[I];
*/
    }
    for (int I=0;I<FileNumber;I++)
      if (WriteFlags[I])
        SrcFile[I]->Write(&Buf[I*RECVOL_BUFSIZE],MaxRead);
  }
  for (int I=0;I<RecVolNumber+FileNumber;I++)
    if (SrcFile[I]!=NULL)
    {
      File *CurFile=SrcFile[I];
      if (NewStyle && WriteFlags[I])
      {
        Int64 Length=CurFile->Tell();
        CurFile->Seek(Length-7,SEEK_SET);
        for (int J=0;J<7;J++)
          CurFile->PutByte(0);
      }
      CurFile->Close();
      SrcFile[I]=NULL;
    }
  if (*LastVolName)
  {
    Archive Arc(Cmd);
    if (Arc.Open(LastVolName,NULL,false,true) && Arc.IsArchive(true) &&
        Arc.SearchBlock(ENDARC_HEAD))
    {
      Arc.Seek(Arc.NextBlockPos,SEEK_SET);
      char Buf[8192];
      int ReadSize=Arc.Read(Buf,sizeof(Buf));
      int ZeroCount=0;
      while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
        ZeroCount++;
      if (ZeroCount==ReadSize)
      {
        Arc.Seek(Arc.NextBlockPos,SEEK_SET);
        Arc.Truncate();
      }
    }
  }
#if !defined(GUI) && !defined(SILENT)
  if (!Cmd->DisablePercentage)
    mprintf("\b\b\b\b100%%");
  if (!Silent && !Cmd->DisableDone)
    mprintf(St(MDone));
#endif
  return(true);
}
Exemplo n.º 21
0
wchar* strcatw(wchar *dest,const wchar *src)
{
  return(strcpyw(dest+strlenw(dest),src));
}
Exemplo n.º 22
0
int ScanTree::FindProc(FindData *FindData)
{
  if (*CurMask==0)
    return(SCAN_NEXT);
  FastFindFile=false;
  if (FindStack[Depth]==NULL)
  {
    bool Wildcards=IsWildcard(CurMask,CurMaskW);
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
    bool IsDir=FindCode && FindData->IsDir;
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   Wildcards && Recurse==RECURSE_WILDCARDS);
    if (Depth==0)
      SearchAllInRoot=SearchAll;
    if (SearchAll || Wildcards)
    {
      FindStack[Depth]=new FindFile;
      char SearchMask[NM];
      strcpy(SearchMask,CurMask);
      if (SearchAll)
        strcpy(PointToName(SearchMask),MASKALL);
      FindStack[Depth]->SetMask(SearchMask);
      if (*CurMaskW)
      {
        wchar SearchMaskW[NM];
        strcpyw(SearchMaskW,CurMaskW);
        if (SearchAll)
          strcpyw(PointToName(SearchMaskW),MASKALLW);
        FindStack[Depth]->SetMaskW(SearchMaskW);
      }
    }
    else
    {
      FastFindFile=true;
      if (!FindCode)
      {
        ErrHandler.OpenErrorMsg(CurMask);
        return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
      }
    }
  }

  if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
  {
    bool Error=FindData->Error;

#ifdef _WIN_32
    if (Error && strstr(CurMask,"System Volume Information\\")!=NULL)
      Error=false;
#endif

#ifndef SILENT
    if (Error)
    {
      Log(NULL,St(MScanError),CurMask);
    }
#endif

    char DirName[NM];
    wchar DirNameW[NM];
    *DirName=0;
    *DirNameW=0;

    delete FindStack[Depth];
    FindStack[Depth--]=NULL;
    while (Depth>=0 && FindStack[Depth]==NULL)
      Depth--;
    if (Depth < 0)
      return(SCAN_DONE);
    char *Slash=strrchrd(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      char Mask[NM];
      strcpy(Mask,Slash);
      *Slash=0;
      strcpy(DirName,CurMask);
      char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        strcpy(CurMask,Mask+1);
      else
        strcpy(PrevSlash,Mask);
    }

    if (*CurMaskW!=0)
    {
      wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
      if (Slash!=NULL)
      {
        wchar Mask[NM];
        strcpyw(Mask,Slash);
        *Slash=0;
        strcpyw(DirNameW,CurMaskW);
        wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
        if (PrevSlash==NULL)
          strcpyw(CurMaskW,Mask+1);
        else
          strcpyw(PrevSlash,Mask);
      }
      if (LowAscii(CurMaskW))
        *CurMaskW=0;
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
      return(Error ? SCAN_ERROR:SCAN_SUCCESS);
    return(Error ? SCAN_ERROR:SCAN_NEXT);
  }

  if (FindData->IsDir)
  {
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);

    char Mask[NM];
    strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
    strcpy(CurMask,FindData->Name);

    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
#ifndef SILENT
      Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
      Log(NULL,St(MPathTooLong));
#endif
      return(SCAN_ERROR);
    }

    AddEndSlash(CurMask);
    strcat(CurMask,Mask);

    if (*CurMaskW && *FindData->NameW==0)
      CharToWide(FindData->Name,FindData->NameW);
    if (*FindData->NameW!=0)
    {
      wchar Mask[NM];
      if (FastFindFile)
        strcpyw(Mask,MASKALLW);
      else
        if (*CurMaskW)
          strcpyw(Mask,PointToName(CurMaskW));
        else
          CharToWide(PointToName(CurMask),Mask);
      strcpyw(CurMaskW,FindData->NameW);
      AddEndSlash(CurMaskW);
      strcatw(CurMaskW,Mask);
    }
    Depth++;
  }
  if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
    return(SCAN_NEXT);
  return(SCAN_SUCCESS);
}
Exemplo n.º 23
0
int ScanTree::FindProc(FindData *FindData)
{
  if (*CurMask==0)
    return(SCAN_NEXT);
  FastFindFile=false;
  if (FindStack[Depth]==NULL)
  {
    bool Wildcards=IsWildcard(CurMask,CurMaskW);
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
    bool IsDir=FindCode && FindData->IsDir;
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   Wildcards && Recurse==RECURSE_WILDCARDS);
    if (Depth==0)
      SearchAllInRoot=SearchAll;
    if (SearchAll || Wildcards)
    {
      FindStack[Depth]=new FindFile;
      char SearchMask[NM];
      strcpy(SearchMask,CurMask);
      if (SearchAll)
        strcpy(PointToName(SearchMask),MASKALL);
      FindStack[Depth]->SetMask(SearchMask);
      if (*CurMaskW)
      {
        wchar SearchMaskW[NM];
        strcpyw(SearchMaskW,CurMaskW);
        if (SearchAll)
          strcpyw(PointToName(SearchMaskW),MASKALLW);
        FindStack[Depth]->SetMaskW(SearchMaskW);
      }
    }
    else
    {
      FastFindFile=true;
      if (!FindCode)
      {
        if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
          return(SCAN_NEXT);
        ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
        return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
      }
    }
  }

  if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
  {
    bool Error=FindData->Error;

#ifdef _WIN_32
    if (Error)
    {
      // Do not display an error if we cannot scan contents of reparse
      // point. Vista contains a lot of reparse (or junction) points,
      // which are not accessible.
      if ((FindData->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
        Error=false;

      // Do not display an error if we cannot scan contents of
      // "System Volume Information" folder. Normally it is not accessible.
      if (strstr(CurMask,"System Volume Information\\")!=NULL)
        Error=false;
    }
#endif

    if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
      Error=false;

#ifndef SILENT
    if (Error)
    {
      Log(NULL,St(MScanError),CurMask);
    }
#endif

    char DirName[NM];
    wchar DirNameW[NM];
    *DirName=0;
    *DirNameW=0;

    delete FindStack[Depth];
    FindStack[Depth--]=NULL;
    while (Depth>=0 && FindStack[Depth]==NULL)
      Depth--;
    if (Depth < 0)
    {
      if (Error)
        Errors++;
      return(SCAN_DONE);
    }
    char *Slash=strrchrd(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      char Mask[NM];
      strcpy(Mask,Slash);
      if (Depth<SetAllMaskDepth)
        strcpy(Mask+1,PointToName(OrigCurMask));
      *Slash=0;
      strcpy(DirName,CurMask);
      char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        strcpy(CurMask,Mask+1);
      else
        strcpy(PrevSlash,Mask);
    }

    if (*CurMaskW!=0)
    {
      wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
      if (Slash!=NULL)
      {
        wchar Mask[NM];
        strcpyw(Mask,Slash);
        if (Depth<SetAllMaskDepth)
          strcpyw(Mask+1,PointToName(OrigCurMaskW));
        *Slash=0;
        strcpyw(DirNameW,CurMaskW);
        wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
        if (PrevSlash==NULL)
          strcpyw(CurMaskW,Mask+1);
        else
          strcpyw(PrevSlash,Mask);
      }
#ifndef _WIN_CE
      if (LowAscii(CurMaskW))
        *CurMaskW=0;
#endif
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
      return(Error ? SCAN_ERROR:SCAN_SUCCESS);
    return(Error ? SCAN_ERROR:SCAN_NEXT);
  }

  if (FindData->IsDir)
  {
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);

//    if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
//      return(SCAN_SUCCESS);

    char Mask[NM];
    bool MaskAll=FastFindFile;

//    bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES);

    strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
    strcpy(CurMask,FindData->Name);

    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
#ifndef SILENT
      Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
      Log(NULL,St(MPathTooLong));
#endif
      return(SCAN_ERROR);
    }

    AddEndSlash(CurMask);
    strcat(CurMask,Mask);

    if (*CurMaskW && *FindData->NameW==0)
      CharToWide(FindData->Name,FindData->NameW);
    if (*FindData->NameW!=0)
    {
      wchar Mask[NM];
      if (FastFindFile)
        strcpyw(Mask,MASKALLW);
      else
        if (*CurMaskW)
          strcpyw(Mask,PointToName(CurMaskW));
        else
          CharToWide(PointToName(CurMask),Mask);
      strcpyw(CurMaskW,FindData->NameW);
      AddEndSlash(CurMaskW);
      strcatw(CurMaskW,Mask);
    }
    Depth++;
    if (MaskAll)
      SetAllMaskDepth=Depth;
  }
  if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
    return(SCAN_NEXT);
  return(SCAN_SUCCESS);
}
Exemplo n.º 24
0
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Command)
{
  RAROptions *Cmd=Arc.GetRAROptions();

  int HeaderType=Arc.GetHeaderType();
  FileHeader *hd=HeaderType==NEWSUB_HEAD ? &Arc.SubHead:&Arc.NewLhd;
  bool SplitHeader=(HeaderType==FILE_HEAD || HeaderType==NEWSUB_HEAD) &&
                   (hd->Flags & LHD_SPLIT_AFTER)!=0;

  if (DataIO!=NULL && SplitHeader && hd->UnpVer>=20 &&
      hd->FileCRC!=0xffffffff && DataIO->PackedCRC!=~hd->FileCRC)
  {
    Log(Arc.FileName,St(MDataBadCRC),hd->FileName,Arc.FileName);
  }

  Int64 PosBeforeClose=Arc.Tell();

  if (DataIO!=NULL)
    DataIO->ProcessedArcSize+=Arc.FileLength();

  Arc.Close();

  char NextName[NM];
  wchar NextNameW[NM];
  strcpy(NextName,Arc.FileName);
  strcpyw(NextNameW,Arc.FileNameW);
  NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);

#if !defined(SFX_MODULE) && !defined(RARDLL)
  bool RecoveryDone=false;
#endif
  bool FailedOpen=false,OldSchemeTested=false;

  while (!Arc.Open(NextName,NextNameW))
  {
    // We need to open a new volume which size was not calculated
    // in total size before, so we cannot calculate the total progress
    // anymore. Let's reset the total size to zero and stop 
    // the total progress.
    if (DataIO!=NULL)
      DataIO->TotalArcSize=0;

    if (!OldSchemeTested)
    {
      // Checking for new style volumes renamed by user to old style
      // name format. Some users did it for unknown reason.
      char AltNextName[NM];
      wchar AltNextNameW[NM];
      strcpy(AltNextName,Arc.FileName);
      strcpyw(AltNextNameW,Arc.FileNameW);
      NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
      OldSchemeTested=true;
      if (Arc.Open(AltNextName,AltNextNameW))
      {
        strcpy(NextName,AltNextName);
        strcpyw(NextNameW,AltNextNameW);
        break;
      }
    }
#ifdef RARDLL
    if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
        Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
    {
      Cmd->DllError=ERAR_EOPEN;
      FailedOpen=true;
      break;
    }
    if (Cmd->ChangeVolProc!=NULL)
    {
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
      _EBX=_ESP;
#endif
      int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
      _ESP=_EBX;
#endif
      if (RetCode==0)
      {
        Cmd->DllError=ERAR_EOPEN;
        FailedOpen=true;
        break;
      }
    }
#else // RARDLL

#if !defined(SFX_MODULE) && !defined(_WIN_CE)
    if (!RecoveryDone)
    {
      RecVolumes RecVol;
      RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
      RecoveryDone=true;
      continue;
    }
#endif

#ifndef GUI
    if (!Cmd->VolumePause && !IsRemovable(NextName))
    {
      FailedOpen=true;
      break;
    }
#endif
#ifndef SILENT
    if (Cmd->AllYes || !AskNextVol(NextName))
#endif
    {
      FailedOpen=true;
      break;
    }

#endif // RARDLL
    *NextNameW=0;
  }
  if (FailedOpen)
  {
#if !defined(SILENT) && !defined(_WIN_CE)
      Log(Arc.FileName,St(MAbsNextVol),NextName);
#endif
    Arc.Open(Arc.FileName,Arc.FileNameW);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return(false);
  }
  Arc.CheckArc(true);
#ifdef RARDLL
  if (Cmd->Callback!=NULL &&
      Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
    return(false);
  if (Cmd->ChangeVolProc!=NULL)
  {
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _EBX=_ESP;
#endif
    int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _ESP=_EBX;
#endif
    if (RetCode==0)
      return(false);
  }
#endif

  if (Command=='T' || Command=='X' || Command=='E')
    mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
  if (SplitHeader)
    Arc.SearchBlock(HeaderType);
  else
    Arc.ReadHeader();
  if (Arc.GetHeaderType()==FILE_HEAD)
  {
    Arc.ConvertAttributes();
    Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
  }
#ifndef GUI
  if (ShowFileName)
  {
    char OutName[NM];
    IntToExt(Arc.NewLhd.FileName,OutName);
#ifdef UNICODE_SUPPORTED
    bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
    if (WideName)
    {
      wchar NameW[NM];
      ConvertPath(Arc.NewLhd.FileNameW,NameW);
      char Name[NM];
      if (WideToChar(NameW,Name) && IsNameUsable(Name))
        strcpy(OutName,Name);
    }
#endif
    mprintf(St(MExtrPoints),OutName);
    if (!Cmd->DisablePercentage)
      mprintf("     ");
  }
#endif
  if (DataIO!=NULL)
  {
    if (HeaderType==ENDARC_HEAD)
      DataIO->UnpVolume=false;
    else
    {
      DataIO->UnpVolume=(hd->Flags & LHD_SPLIT_AFTER);
      DataIO->SetPackedSizeToRead(hd->FullPackSize);
    }
#ifdef SFX_MODULE
    DataIO->UnpArcSize=Arc.FileLength();
#endif
    
    // Reset the size of packed data read from current volume. It is used
    // to display the total progress and preceding volumes are already
    // compensated with ProcessedArcSize, so we need to reset this variable.
    DataIO->CurUnpRead=0;

    DataIO->PackedCRC=0xffffffff;
//    DataIO->SetFiles(&Arc,NULL);
  }
  return(true);
}
Exemplo n.º 25
0
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,bool &Repeat)
{
  char Command=*Cmd->Command;
  if (HeaderSize==0)
    if (DataIO.UnpVolume)
    {
#ifdef NOVOLUME
      return(false);
#else
      if (!MergeArchive(Arc,&DataIO,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,&DataIO,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>=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];
    if (WideToChar(ArcFileNameW,Name) && 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)!=0;
  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),ArcFileName);
#ifdef RARDLL
      Cmd->DllError=ERAR_BAD_DATA;
#endif
      ErrHandler.SetErrorCode(OPEN_ERROR);
    }
    ExactMatch=false;
  }

  FirstFile=false;
#endif

  if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
  {
    if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
#ifndef RARDLL
      if (*Password==0)
#endif
      {
#ifdef RARDLL
        if (*Cmd->Password==0)
          if (Cmd->Callback==NULL ||
              Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)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),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)
    {
      strcat(DestFileName,PointToName(Arc.FirstVolumeName));
      SetExt(DestFileName,NULL);
      AddEndSlash(DestFileName);
    }
#endif

    char *ExtrName=ArcFileName;

    bool EmptyName=false;
#ifndef SFX_MODULE
    size_t Length=strlen(Cmd->ArcPath);
    if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) &&
        strlen(ArcFileName)==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 (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
      strcat(DestFileName,PointToName(ExtrName));
    else
      strcat(DestFileName,ExtrName);

    char DiskLetter=etoupper(DestFileName[0]);

    if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]) &&
        DiskLetter>='A' && DiskLetter<='Z')
      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.FirstVolumeNameW!=0)
          strcpyw(FileNameW,Arc.FirstVolumeNameW);
        else
          CharToWide(Arc.FirstVolumeName,FileNameW);
        strcatw(DestFileNameW,PointToName(FileNameW));
        SetExt(DestFileNameW,NULL);
        AddEndSlash(DestFileNameW);
      }
#endif
      wchar *ExtrNameW=ArcFileNameW;
#ifndef SFX_MODULE
      if (Length>0)
      {
        wchar ArcPathW[NM];
        GetWideName(Cmd->ArcPath,Cmd->ArcPathW,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;

    if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
    {
      struct FindData FD;
      if (FindFile::FastFind(DestFileName,DestNameW,&FD))
      {
        if (FD.mtime >= Arc.NewLhd.mtime)
        {
          // If directory already exists and its modification time is newer 
          // than start of extraction, it is likely it was created 
          // when creating a path to one of already extracted items. 
          // In such case we'll better update its time even if archived 
          // directory is older.

          if (!FD.IsDir || FD.mtime<StartTime)
            ExtrFile=false;
        }
      }
      else
        if (Cmd->FreshFiles)
          ExtrFile=false;
    }

    // Skip encrypted file if no password is specified.
    if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
    {
      ErrHandler.SetErrorCode(WARNING);
#ifdef RARDLL
      Cmd->DllError=ERAR_MISSING_PASSWORD;
#endif
      ExtrFile=false;
    }

#ifdef RARDLL
    if (*Cmd->DllDestName)
    {
      strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
      *DestFileNameW=0;
      if (Cmd->DllOpMode!=RAR_EXTRACT)
        ExtrFile=false;
    }
    if (*Cmd->DllDestNameW)
    {
      strncpyzw(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
      DestNameW=DestFileNameW;
      if (Cmd->DllOpMode!=RAR_EXTRACT)
        ExtrFile=false;
    }
#endif

#ifdef SFX_MODULE
    if ((Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.UnpVer!=29) &&
        Arc.NewLhd.Method!=0x30)
#else
    if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
#endif
    {
#ifndef SILENT
      Log(Arc.FileName,St(MUnknownMeth),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),ArcFileName);
#endif
          return(true);
        }
        TotalFileCount++;
        if (Cmd->Test)
        {
#ifndef GUI
          mprintf(St(MExtrTestFile),ArcFileName);
          mprintf(" %s",St(MOk));
#endif
          return(true);
        }
        MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
        bool DirExist=false;
        if (MDCode!=MKDIR_SUCCESS)
        {
          DirExist=FileExist(DestFileName,DestNameW);
          if (DirExist && !IsDir(GetFileAttr(DestFileName,DestNameW)))
          {
            bool UserReject;
            FileCreate(Cmd,NULL,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime);
            DirExist=false;
          }
          CreatePath(DestFileName,DestNameW,true);
          MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
        }
        if (MDCode==MKDIR_SUCCESS)
        {
#ifndef GUI
          mprintf(St(MCreatDir),DestFileName);
          mprintf(" %s",St(MOk));
#endif
          PrevExtracted=true;
        }
        else
          if (DirExist)
          {
            if (!Cmd->IgnoreGeneralAttr)
              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)
        {
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
          if (Cmd->SetCompressedAttr &&
              (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
            SetFileCompression(DestFileName,DestNameW,true);
#endif
          SetDirTime(DestFileName,DestNameW,
            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 (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
          {
            ExtrFile=false;
            if (!UserReject)
            {
              ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
              ErrHandler.SetErrorCode(CREATE_ERROR);
#ifdef RARDLL
              Cmd->DllError=ERAR_ECREATE;
#endif
              if (!IsNameUsable(DestFileName))
              {
                Log(Arc.FileName,St(MCorrectingName));
                char OrigName[sizeof(DestFileName)];
                strncpyz(OrigName,DestFileName,ASIZE(OrigName));

                MakeNameUsable(DestFileName,true);
                CreatePath(DestFileName,NULL,true);
                if (FileCreate(Cmd,&CurFile,DestFileName,NULL,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
                {
#ifndef SFX_MODULE
                  Log(Arc.FileName,St(MRenaming),OrigName,DestFileName);
#endif
                  ExtrFile=true;
                }
                else
                  ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
              }
            }
          }
        }
      }

    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),ArcFileName);
        else
          switch(Cmd->Test ? 'T':Command)
          {
            case 'T':
              mprintf(St(MExtrTestFile),ArcFileName);
              break;
#ifndef SFX_MODULE
            case 'P':
              mprintf(St(MExtrPrinting),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,
        Arc.NewLhd.UnpVer>=36);
      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)!=0);
          }

      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;
/*
        else
          Arc.NewLhd.FileAttr|=FA_ARCH; //set archive bit for unpacked files (file is not backed up)
*/
#endif
        if (!BrokenFile || Cmd->KeepBroken)
        {
          if (BrokenFile)
            CurFile.Truncate();
          CurFile.SetOpenFileTime(
            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();
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
          if (Cmd->SetCompressedAttr &&
              (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
            SetFileCompression(CurFile.FileName,CurFile.FileNameW,true);
#endif
          CurFile.SetCloseFileTime(
            Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
            Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
          if (!Cmd->IgnoreGeneralAttr)
            SetFileAttr(CurFile.FileName,CurFile.FileNameW,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);
}