Example #1
0
uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
{
  SaveFilePos SavePos(*SrcFile);
  const size_t BufSize=0x10000;
  Array<byte> Data(BufSize);
  int64 BlockCount=0;
  uint DataCRC=0xffffffff;

#if !defined(SILENT) && !defined(_WIN_CE)
  int64 FileLength=SrcFile->FileLength();
  if (ShowMode!=CALCCRC_SHOWNONE)
  {
    mprintf(St(MCalcCRC));
    mprintf("     ");
  }

#endif

  SrcFile->Seek(0,SEEK_SET);
  while (true)
  {
    size_t SizeToRead;
    if (Size==INT64NDF)   // If we process the entire file.
      SizeToRead=BufSize; // Then always attempt to read the entire buffer.
    else
      SizeToRead=(size_t)Min((int64)BufSize,Size);
    int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
    if (ReadSize==0)
      break;

    ++BlockCount;
    if ((BlockCount & 15)==0)
    {
#if !defined(SILENT) && !defined(_WIN_CE)
      if (ShowMode==CALCCRC_SHOWALL)
        mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
#endif
      Wait();
    }
    DataCRC=CRC(DataCRC,&Data[0],ReadSize);
    if (Size!=INT64NDF)
      Size-=ReadSize;
  }
#if !defined(SILENT) && !defined(_WIN_CE)
  if (ShowMode==CALCCRC_SHOWALL)
    mprintf("\b\b\b\b    ");
#endif
  return(DataCRC^0xffffffff);
}
Example #2
0
void ComprDataIO::ShowUnpRead(Int64 ArcPos,Int64 ArcSize)
{
  if (ShowProgress && SrcFile!=NULL)
  {
    Archive *SrcArc=(Archive *)SrcFile;
    RAROptions *Cmd=SrcArc->GetRAROptions();
    if (TotalArcSize!=0)
      ArcSize=TotalArcSize;
    ArcPos+=ProcessedArcSize;
    if (!SrcArc->Volume)
    {
      int CurPercent=ToPercent(ArcPos,ArcSize);
      if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
      {
        mprintf("\b\b\b\b%3d%%",CurPercent);
        LastPercent=CurPercent;
      }
    }
  }
}
Example #3
0
void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
{
  if (ShowProgress && SrcFile!=NULL)
  {
    if (TotalArcSize!=0)
    {
      // important when processing several archives or multivolume archive
      ArcSize=TotalArcSize;
      ArcPos+=ProcessedArcSize;
    }

    Archive *SrcArc=(Archive *)SrcFile;
    RAROptions *Cmd=SrcArc->GetRAROptions();

    int CurPercent=ToPercent(ArcPos,ArcSize);
    if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
    {
      LastPercent=CurPercent;
    }
  }
}
Example #4
0
void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
{
  return;	// OPENMPT ADDITION
  if (ShowProgress && SrcFile!=NULL)
  {
    if (TotalArcSize!=0)
    {
      // important when processing several archives or multivolume archive
      ArcSize=TotalArcSize;
      ArcPos+=ProcessedArcSize;
    }

    Archive *SrcArc=(Archive *)SrcFile;
    RAROptions *Cmd=SrcArc->GetRAROptions();

    int CurPercent=ToPercent(ArcPos,ArcSize);
    if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
    {
      uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize);
      LastPercent=CurPercent;
    }
  }
}
Example #5
0
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
{
  SaveFilePos SavePos(*SrcFile);
#ifndef SILENT
  int64 FileLength=SrcFile->FileLength();
  if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWALL))!=0)
  {
    mprintf(St(MCalcCRC));
    mprintf(L"     ");
  }

#endif

  if ((Flags & CALCFSUM_CURPOS)==0)
    SrcFile->Seek(0,SEEK_SET);

  const size_t BufSize=0x100000;
  Array<byte> Data(BufSize);


  DataHash HashCRC,HashBlake2;
  HashCRC.Init(HASH_CRC32,Threads);
  HashBlake2.Init(HASH_BLAKE2,Threads);

  int64 BlockCount=0;
  while (true)
  {
    size_t SizeToRead;
    if (Size==INT64NDF)   // If we process the entire file.
      SizeToRead=BufSize; // Then always attempt to read the entire buffer.
    else
      SizeToRead=(size_t)Min((int64)BufSize,Size);
    int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
    if (ReadSize==0)
      break;

    if ((++BlockCount & 0xf)==0)
    {
#ifndef SILENT
      if ((Flags & CALCFSUM_SHOWALL)!=0)
        mprintf(L"\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
#endif
      Wait();
    }

    if (CRC32!=NULL)
      HashCRC.Update(&Data[0],ReadSize);
    if (Blake2!=NULL)
      HashBlake2.Update(&Data[0],ReadSize);

    if (Size!=INT64NDF)
      Size-=ReadSize;
  }
#ifndef SILENT
  if ((Flags & CALCFSUM_SHOWALL)!=0)
    mprintf(L"\b\b\b\b    ");
#endif

  if (CRC32!=NULL)
    *CRC32=HashCRC.GetCRC32();
  if (Blake2!=NULL)
  {
    HashValue Result;
    HashBlake2.Result(&Result);
    memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
  }
}
Example #6
0
size_t Archive::ReadHeader15()
{
  RawRead Raw(this);

  bool Decrypt=Encrypted && CurBlockPos>(int64)SFXSize+SIZEOF_MARKHEAD3;

  if (Decrypt)
  {
#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
    return 0;
#else
    RequestArcPassword();

    byte Salt[SIZE_SALT30];
    if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30)
    {
      UnexpEndArcMsg();
      return 0;
    }
    HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL);
    Raw.SetCrypt(&HeadersCrypt);
#endif
  }

  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  if (Raw.Size()==0)
  {
    UnexpEndArcMsg();
    return 0;
  }

  ShortBlock.HeadCRC=Raw.Get2();

  ShortBlock.Reset();

  uint HeaderType=Raw.Get1();
  ShortBlock.Flags=Raw.Get2();
  ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0;
  ShortBlock.HeadSize=Raw.Get2();

  ShortBlock.HeaderType=(HEADER_TYPE)HeaderType;
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  {
    BrokenHeaderMsg();
    return 0;
  }

  // For simpler further processing we map header types common
  // for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include
  // header types specific for RAR 1.5 - 4.x only.
  switch(ShortBlock.HeaderType)
  {
    case HEAD3_MAIN:    ShortBlock.HeaderType=HEAD_MAIN;     break;
    case HEAD3_FILE:    ShortBlock.HeaderType=HEAD_FILE;     break;
    case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE;  break;
    case HEAD3_ENDARC:  ShortBlock.HeaderType=HEAD_ENDARC;   break;
  }
  CurHeaderType=ShortBlock.HeaderType;

  if (ShortBlock.HeaderType==HEAD3_CMT)
  {
    // Old style (up to RAR 2.9) comment header embedded into main
    // or file header. We must not read the entire ShortBlock.HeadSize here
    // to not break the comment processing logic later.
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  }
  else
    if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
    {
      // Old style (up to RAR 2.9) main archive comment embedded into
      // the main archive header found. While we can read the entire 
      // ShortBlock.HeadSize here and remove this part of "if", it would be
      // waste of memory, because we'll read and process this comment data
      // in other function anyway and we do not need them here now.
      Raw.Read(SIZEOF_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD);
    }
    else
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);

  NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);

  switch(ShortBlock.HeaderType)
  {
    case HEAD_MAIN:
      MainHead.Reset();
      *(BaseBlock *)&MainHead=ShortBlock;
      MainHead.HighPosAV=Raw.Get2();
      MainHead.PosAV=Raw.Get4();

      Volume=(MainHead.Flags & MHD_VOLUME)!=0;
      Solid=(MainHead.Flags & MHD_SOLID)!=0;
      Locked=(MainHead.Flags & MHD_LOCK)!=0;
      Protected=(MainHead.Flags & MHD_PROTECT)!=0;
      Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
      Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
      MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
    
      // Only for encrypted 3.0+ archives. 2.x archives did not have this
      // flag, so for non-encrypted archives, we'll set it later based on
      // file attributes.
      FirstVolume=(MainHead.Flags & MHD_FIRSTVOLUME)!=0;

      NewNumbering=(MainHead.Flags & MHD_NEWNUMBERING)!=0;
      break;
    case HEAD_FILE:
    case HEAD_SERVICE:
      {
        bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
        FileHeader *hd=FileBlock ? &FileHead:&SubHead;
        hd->Reset();

        *(BaseBlock *)hd=ShortBlock;

        hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
        hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
        hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
        hd->SaltSet=(hd->Flags & LHD_SALT)!=0;
        hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
        hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
        hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
        hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
        hd->Version=(hd->Flags & LHD_VERSION)!=0;
        
        hd->DataSize=Raw.Get4();
        uint LowUnpSize=Raw.Get4();
        hd->HostOS=Raw.Get1();

        hd->FileHash.Type=HASH_CRC32;
        hd->FileHash.CRC32=Raw.Get4();

        uint FileTime=Raw.Get4();
        hd->UnpVer=Raw.Get1();
        hd->Method=Raw.Get1()-0x30;
        size_t NameSize=Raw.Get2();
        hd->FileAttr=Raw.Get4();

        hd->CryptMethod=CRYPT_NONE;
        if (hd->Encrypted)
          switch(hd->UnpVer)
          {
            case 13: hd->CryptMethod=CRYPT_RAR13; break;
            case 15: hd->CryptMethod=CRYPT_RAR15; break;
            case 20: 
            case 26: hd->CryptMethod=CRYPT_RAR20; break;
            default: hd->CryptMethod=CRYPT_RAR30; break;
          }

        hd->HSType=HSYS_UNKNOWN;
        if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
          hd->HSType=HSYS_UNIX;
        else
          if (hd->HostOS<HOST_MAX)
            hd->HSType=HSYS_WINDOWS;

        hd->RedirType=FSREDIR_NONE;

        // RAR 4.x Unix symlink.
        if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
        {
          hd->RedirType=FSREDIR_UNIXSYMLINK;
          *hd->RedirName=0;
        }

        hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
        
        hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;

        uint HighPackSize,HighUnpSize;
        if (hd->LargeFile)
        {
          HighPackSize=Raw.Get4();
          HighUnpSize=Raw.Get4();
          hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
        }
        else 
        {
          HighPackSize=HighUnpSize=0;
          // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
          // that we do not know the unpacked file size and must unpack it
          // until we find the end of file marker in compressed data.
          hd->UnknownUnpSize=(LowUnpSize==0xffffffff);
        }
        hd->PackSize=INT32TO64(HighPackSize,hd->DataSize);
        hd->UnpSize=INT32TO64(HighUnpSize,LowUnpSize);
        if (hd->UnknownUnpSize)
          hd->UnpSize=INT64NDF;

        char FileName[NM*4];
        size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
        Raw.GetB((byte *)FileName,ReadNameSize);
        FileName[ReadNameSize]=0;

        if (FileBlock)
        {
          if ((hd->Flags & LHD_UNICODE)!=0)
          {
            EncodeFileName NameCoder;
            size_t Length=strlen(FileName);
            Length++;
            NameCoder.Decode(FileName,(byte *)FileName+Length,
                             NameSize-Length,hd->FileName,
                             ASIZE(hd->FileName));
          }
          else
            *hd->FileName=0;

          char AnsiName[NM];
          IntToExt(FileName,AnsiName,ASIZE(AnsiName));
          GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));

#ifndef SFX_MODULE
          ConvertNameCase(hd->FileName);
#endif
          ConvertFileHeader(hd);
        }
        else
        {
          CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));

          // Calculate the size of optional data.
          int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
          if ((hd->Flags & LHD_SALT)!=0)
            DataSize-=SIZE_SALT30;

          if (DataSize>0)
          {
            // Here we read optional additional fields for subheaders.
            // They are stored after the file name and before salt.
            hd->SubData.Alloc(DataSize);
            Raw.GetB(&hd->SubData[0],DataSize);
            if (hd->CmpName(SUBHEAD_TYPE_RR))
            {
              byte *D=&hd->SubData[8];
              RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
              RecoverySize*=512; // Sectors to size.
              int64 CurPos=Tell();
              RecoveryPercent=ToPercent(RecoverySize,CurPos);
              // Round fractional percent exceeding .5 to upper value.
              if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent)
                RecoveryPercent++;
            }
          }

          if (hd->CmpName(SUBHEAD_TYPE_CMT))
            MainComment=true;
        }
        if ((hd->Flags & LHD_SALT)!=0)
          Raw.GetB(hd->Salt,SIZE_SALT30);
        hd->mtime.SetDos(FileTime);
        if ((hd->Flags & LHD_EXTTIME)!=0)
        {
          ushort Flags=Raw.Get2();
          RarTime *tbl[4];
          tbl[0]=&FileHead.mtime;
          tbl[1]=&FileHead.ctime;
          tbl[2]=&FileHead.atime;
          tbl[3]=NULL; // Archive time is not used now.
          for (int I=0;I<4;I++)
          {
            RarTime *CurTime=tbl[I];
            uint rmode=Flags>>(3-I)*4;
            if ((rmode & 8)==0 || CurTime==NULL)
              continue;
            if (I!=0)
            {
              uint DosTime=Raw.Get4();
              CurTime->SetDos(DosTime);
            }
            RarLocalTime rlt;
            CurTime->GetLocal(&rlt);
            if (rmode & 4)
              rlt.Second++;
            rlt.Reminder=0;
            int count=rmode&3;
            for (int J=0;J<count;J++)
            {
              byte CurByte=Raw.Get1();
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
            }
            CurTime->SetLocal(&rlt);
          }
        }
        NextBlockPos+=hd->PackSize;
        bool CRCProcessedOnly=hd->CommentInHeader;
        ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
        if (hd->HeadCRC!=HeaderCRC)
        {
          BrokenHeader=true;
          ErrHandler.SetErrorCode(RARX_WARNING);

          // If we have a broken encrypted header, we do not need to display
          // the error message here, because it will be displayed for such
          // headers later in this function. Also such headers are unlikely
          // to have anything sensible in file name field, so it is useless
          // to display the file name.
          if (!Decrypt)
            uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
        }
      }
      break;
    case HEAD_ENDARC:
      *(BaseBlock *)&EndArcHead=ShortBlock;
      EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
      EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
      EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
      EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
      if (EndArcHead.DataCRC)
        EndArcHead.ArcDataCRC=Raw.Get4();
      if (EndArcHead.StoreVolNumber)
        VolNumber=EndArcHead.VolNumber=Raw.Get2();
      break;
#ifndef SFX_MODULE
    case HEAD3_CMT:
      *(BaseBlock *)&CommHead=ShortBlock;
      CommHead.UnpSize=Raw.Get2();
      CommHead.UnpVer=Raw.Get1();
      CommHead.Method=Raw.Get1();
      CommHead.CommCRC=Raw.Get2();
      break;
    case HEAD3_SIGN:
      *(BaseBlock *)&SignHead=ShortBlock;
      SignHead.CreationTime=Raw.Get4();
      SignHead.ArcNameSize=Raw.Get2();
      SignHead.UserNameSize=Raw.Get2();
      break;
    case HEAD3_AV:
      *(BaseBlock *)&AVHead=ShortBlock;
      AVHead.UnpVer=Raw.Get1();
      AVHead.Method=Raw.Get1();
      AVHead.AVVer=Raw.Get1();
      AVHead.AVInfoCRC=Raw.Get4();
      break;
    case HEAD3_PROTECT:
      *(BaseBlock *)&ProtectHead=ShortBlock;
      ProtectHead.DataSize=Raw.Get4();
      ProtectHead.Version=Raw.Get1();
      ProtectHead.RecSectors=Raw.Get2();
      ProtectHead.TotalBlocks=Raw.Get4();
      Raw.GetB(ProtectHead.Mark,8);
      NextBlockPos+=ProtectHead.DataSize;
      RecoverySize=ProtectHead.RecSectors*512;
      break;
    case HEAD3_OLDSERVICE:
      *(BaseBlock *)&SubBlockHead=ShortBlock;
      SubBlockHead.DataSize=Raw.Get4();
      NextBlockPos+=SubBlockHead.DataSize;
      SubBlockHead.SubType=Raw.Get2();
      SubBlockHead.Level=Raw.Get1();
      switch(SubBlockHead.SubType)
      {
        case UO_HEAD:
          *(SubBlockHeader *)&UOHead=SubBlockHead;
          UOHead.OwnerNameSize=Raw.Get2();
          UOHead.GroupNameSize=Raw.Get2();
          if (UOHead.OwnerNameSize>=ASIZE(UOHead.OwnerName))
            UOHead.OwnerNameSize=ASIZE(UOHead.OwnerName)-1;
          if (UOHead.GroupNameSize>=ASIZE(UOHead.GroupName))
            UOHead.GroupNameSize=ASIZE(UOHead.GroupName)-1;
          Raw.GetB(UOHead.OwnerName,UOHead.OwnerNameSize);
          Raw.GetB(UOHead.GroupName,UOHead.GroupNameSize);
          UOHead.OwnerName[UOHead.OwnerNameSize]=0;
          UOHead.GroupName[UOHead.GroupNameSize]=0;
          break;
        case MAC_HEAD:
          *(SubBlockHeader *)&MACHead=SubBlockHead;
          MACHead.fileType=Raw.Get4();
          MACHead.fileCreator=Raw.Get4();
          break;
        case EA_HEAD:
        case BEEA_HEAD:
        case NTACL_HEAD:
          *(SubBlockHeader *)&EAHead=SubBlockHead;
          EAHead.UnpSize=Raw.Get4();
          EAHead.UnpVer=Raw.Get1();
          EAHead.Method=Raw.Get1();
          EAHead.EACRC=Raw.Get4();
          break;
        case STREAM_HEAD:
          *(SubBlockHeader *)&StreamHead=SubBlockHead;
          StreamHead.UnpSize=Raw.Get4();
          StreamHead.UnpVer=Raw.Get1();
          StreamHead.Method=Raw.Get1();
          StreamHead.StreamCRC=Raw.Get4();
          StreamHead.StreamNameSize=Raw.Get2();
          if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName))
            StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1;
          Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize);
          StreamHead.StreamName[StreamHead.StreamNameSize]=0;
          break;
      }
      break;
#endif
    default:
      if (ShortBlock.Flags & LONG_BLOCK)
        NextBlockPos+=Raw.Get4();
      break;
  }
Example #7
0
void QuickView::DisplayObject()
{
	if (m_Flags.Check(FSCROBJ_ISREDRAWING))
		return;

	m_Flags.Set(FSCROBJ_ISREDRAWING);

	if (!QView && !ProcessingPluginCommand)
		Parent()->GetAnotherPanel(this)->UpdateViewPanel();

	if (this->Destroyed())
		return;

	if (QView)
		QView->SetPosition(m_X1+1,m_Y1+1,m_X2-1,m_Y2-3);

	Box(m_X1,m_Y1,m_X2,m_Y2,colors::PaletteColorToFarColor(COL_PANELBOX),DOUBLE_BOX);
	SetScreen(m_X1+1,m_Y1+1,m_X2-1,m_Y2-1,L' ',colors::PaletteColorToFarColor(COL_PANELTEXT));
	SetColor(m_Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE);

	string strTitle = GetTitle();
	if (!strTitle.empty())
	{
		GotoXY(m_X1+(m_X2-m_X1+1-(int)strTitle.size())/2,m_Y1);
		Text(strTitle);
	}

	DrawSeparator(m_Y2-2);
	SetColor(COL_PANELTEXT);
	GotoXY(m_X1+1,m_Y2-1);
	Global->FS << fmt::LeftAlign()<<fmt::ExactWidth(m_X2-m_X1-1)<<PointToName(strCurFileName);

	if (!strCurFileType.empty())
	{
		string strTypeText=L" ";
		strTypeText+=strCurFileType;
		strTypeText+=L" ";
		TruncStr(strTypeText,m_X2-m_X1-1);
		SetColor(COL_PANELSELECTEDINFO);
		GotoXY(m_X1+(m_X2-m_X1+1-(int)strTypeText.size())/2,m_Y2-2);
		Text(strTypeText);
	}

	if (Directory)
	{
		FormatString FString;
		string DisplayName(strCurFileName);
		TruncPathStr(DisplayName,std::max(0, m_X2-m_X1-1-StrLength(MSG(MQuickViewFolder))-5));
		FString<<MSG(MQuickViewFolder)<<L" \""<<DisplayName<<L"\"";
		SetColor(COL_PANELTEXT);
		GotoXY(m_X1+2,m_Y1+2);
		PrintText(FString);

		DWORD currAttr=os::GetFileAttributes(strCurFileName); // обламывается, если нет доступа
		if (currAttr != INVALID_FILE_ATTRIBUTES && (currAttr&FILE_ATTRIBUTE_REPARSE_POINT))
		{
			string Tmp, Target;
			DWORD ReparseTag=0;
			const wchar_t* PtrName;
			if (GetReparsePointInfo(strCurFileName, Target, &ReparseTag))
			{
				NormalizeSymlinkName(Target);
				switch(ReparseTag)
				{
				// 0xA0000003L = Directory Junction or Volume Mount Point
				case IO_REPARSE_TAG_MOUNT_POINT:
					{
						LNGID ID_Msg = MQuickViewJunction;
						bool Root;
						if(ParsePath(Target, nullptr, &Root) == PATH_VOLUMEGUID && Root)
						{
							ID_Msg=MQuickViewVolMount;
						}
						PtrName = MSG(ID_Msg);
					}
					break;
				// 0xA000000CL = Directory or File Symbolic Link
				case IO_REPARSE_TAG_SYMLINK:
					PtrName = MSG(MQuickViewSymlink);
					break;
				// 0x8000000AL = Distributed File System
				case IO_REPARSE_TAG_DFS:
					PtrName = MSG(MQuickViewDFS);
					break;
				// 0x80000012L = Distributed File System Replication
				case IO_REPARSE_TAG_DFSR:
					PtrName = MSG(MQuickViewDFSR);
					break;
				// 0xC0000004L = Hierarchical Storage Management
				case IO_REPARSE_TAG_HSM:
					PtrName = MSG(MQuickViewHSM);
					break;
				// 0x80000006L = Hierarchical Storage Management2
				case IO_REPARSE_TAG_HSM2:
					PtrName = MSG(MQuickViewHSM2);
					break;
				// 0x80000007L = Single Instance Storage
				case IO_REPARSE_TAG_SIS:
					PtrName = MSG(MQuickViewSIS);
					break;
				// 0x80000008L = Windows Imaging Format
				case IO_REPARSE_TAG_WIM:
					PtrName = MSG(MQuickViewWIM);
					break;
				// 0x80000009L = Cluster Shared Volumes
				case IO_REPARSE_TAG_CSV:
					PtrName = MSG(MQuickViewCSV);
					break;
				case IO_REPARSE_TAG_DEDUP:
					PtrName = MSG(MQuickViewDEDUP);
					break;
				case IO_REPARSE_TAG_NFS:
					PtrName = MSG(MQuickViewNFS);
					break;
				case IO_REPARSE_TAG_FILE_PLACEHOLDER:
					PtrName = MSG(MQuickViewPlaceholder);
					break;
					// 0x????????L = anything else
				default:
					if (Global->Opt->ShowUnknownReparsePoint)
					{
						Tmp = FormatString() << L":" << fmt::Radix(16) << fmt::ExactWidth(8) << fmt::FillChar(L'0') << ReparseTag;
						PtrName = Tmp.data();
					}
					else
					{
						PtrName=MSG(MQuickViewUnknownReparsePoint);
					}
				}
			}
			else
			{
				PtrName = MSG(MQuickViewUnknownReparsePoint);
				Target = MSG(MQuickViewNoData);
			}

			TruncPathStr(Target,std::max(0, m_X2-m_X1-1-StrLength(PtrName)-5));
			FString.clear();
			FString<<PtrName<<L" \""<<Target<<L"\"";
			SetColor(COL_PANELTEXT);
			GotoXY(m_X1+2,m_Y1+3);
			PrintText(FString);
		}

		if (Directory==1 || Directory==4)
		{
			const auto iColor = uncomplete_dirscan? COL_PANELHIGHLIGHTTEXT : COL_PANELINFOTEXT;
			const wchar_t *prefix = uncomplete_dirscan ? L"~" : L"";
			GotoXY(m_X1+2,m_Y1+4);
			PrintText(MSG(MQuickViewContains));
			GotoXY(m_X1+2,m_Y1+6);
			PrintText(MSG(MQuickViewFolders));
			SetColor(iColor);
			FString.clear();
			FString<<prefix<<Data.DirCount;
			PrintText(FString);
			SetColor(COL_PANELTEXT);
			GotoXY(m_X1+2,m_Y1+7);
			PrintText(MSG(MQuickViewFiles));
			SetColor(iColor);
			FString.clear();
			FString<<prefix<<Data.FileCount;
			PrintText(FString);
			SetColor(COL_PANELTEXT);
			GotoXY(m_X1+2,m_Y1+8);
			PrintText(MSG(MQuickViewBytes));
			SetColor(iColor);
			string strSize;
			InsertCommas(Data.FileSize,strSize);
			PrintText(prefix+strSize);
			SetColor(COL_PANELTEXT);
			GotoXY(m_X1+2,m_Y1+9);
			PrintText(MSG(MQuickViewAllocated));
			SetColor(iColor);
			InsertCommas(Data.AllocationSize,strSize);
			FString.clear();
			FString << prefix << strSize << L" (" << ToPercent(Data.AllocationSize,Data.FileSize) << L"%)";
			PrintText(FString);

			if (Directory!=4)
			{
				SetColor(COL_PANELTEXT);
				GotoXY(m_X1+2,m_Y1+11);
				PrintText(MSG(MQuickViewCluster));
				SetColor(iColor);
				InsertCommas(Data.ClusterSize,strSize);
				PrintText(prefix+strSize);

				SetColor(COL_PANELTEXT);
				GotoXY(m_X1+2,m_Y1+12);
				PrintText(MSG(MQuickViewSlack));
				SetColor(iColor);
				InsertCommas(Data.FilesSlack, strSize);
				FString.clear();
				FString << prefix << strSize << L" (" << ToPercent(Data.FilesSlack, Data.AllocationSize) << L"%)";
				PrintText(FString);

				SetColor(COL_PANELTEXT);
				GotoXY(m_X1+2,m_Y1+13);
				PrintText(MSG(MQuickViewMFTOverhead));
				SetColor(iColor);
				InsertCommas(Data.MFTOverhead, strSize);
				FString.clear();
				FString<<prefix<<strSize<<L" ("<<ToPercent(Data.MFTOverhead, Data.AllocationSize)<<L"%)";
				PrintText(FString);

			}
		}
	}
	else if (QView)
		QView->Show();

	m_Flags.Clear(FSCROBJ_ISREDRAWING);
}
Example #8
0
bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
{
  wchar ArcName[NM];
  wcscpy(ArcName,Name);

  wchar *Num=GetVolNumPart(ArcName);
  while (Num>ArcName && IsDigit(*(Num-1)))
    Num--;
  wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName));
  
  wchar FirstVolName[NM];
  *FirstVolName=0;

  int64 RecFileSize=0;

  FindFile VolFind;
  VolFind.SetMask(ArcName);
  FindData fd;
  uint FoundRecVolumes=0;
  while (VolFind.Next(&fd))
  {
    Wait();

    Archive *Vol=new Archive(Cmd);
    int ItemPos=-1;
    if (Vol->WOpen(fd.Name))
    {
      if (CmpExt(fd.Name,L"rev"))
      {
        uint RecNum=ReadHeader(Vol,FoundRecVolumes==0);
        if (RecNum!=0)
        {
          if (FoundRecVolumes==0)
            RecFileSize=Vol->FileLength();

          ItemPos=RecNum;
          FoundRecVolumes++;
        }
      }
      else
        if (Vol->IsArchive(true) && (Vol->SFXSize>0 || CmpExt(fd.Name,L"rar")))
        {
          if (!Vol->Volume && !Vol->BrokenHeader)
          {
            uiMsg(UIERROR_NOTVOLUME,ArcName);
            return false;
          }
          // We work with archive as with raw data file, so we do not want
          // to spend time to QOpen I/O redirection.
          Vol->QOpenUnload();
      
          Vol->Seek(0,SEEK_SET);

          // RAR volume found. Get its number, store the handle in appropriate
          // array slot, clean slots in between if we had to grow the array.
          wchar *Num=GetVolNumPart(fd.Name);
          uint VolNum=0;
          for (uint K=1;Num>=fd.Name && IsDigit(*Num);K*=10,Num--)
            VolNum+=(*Num-'0')*K;
          if (VolNum==0 || VolNum>MaxVolumes)
            continue;
          size_t CurSize=RecItems.Size();
          if (VolNum>CurSize)
          {
            RecItems.Alloc(VolNum);
            for (size_t I=CurSize;I<VolNum;I++)
              RecItems[I].f=NULL;
          }
          ItemPos=VolNum-1;

          if (*FirstVolName==0)
            VolNameToFirstName(fd.Name,FirstVolName,ASIZE(FirstVolName),true);
        }
    }
    if (ItemPos==-1)
      delete Vol; // Skip found file, it is not RAR or REV volume.
    else
      if ((uint)ItemPos<RecItems.Size()) // Check if found more REV than needed.
      {
        // Store found RAR or REV volume.
        RecVolItem *Item=RecItems+ItemPos;
        Item->f=Vol;
        Item->New=false;
        wcsncpyz(Item->Name,fd.Name,ASIZE(Item->Name));
      }
  }

  if (!Silent || FoundRecVolumes!=0)
    uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
  if (FoundRecVolumes==0)
    return false;

  uiMsg(UIMSG_RECVOLCALCCHECKSUM);

  MissingVolumes=0;
  for (uint I=0;I<TotalCount;I++)
  {
    RecVolItem *Item=&RecItems[I];
    if (Item->f!=NULL)
    {
      uiMsg(UIMSG_STRING,Item->Name);

      uint RevCRC;
      CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS);
      Item->Valid=RevCRC==Item->CRC;
      if (!Item->Valid)
      {
        uiMsg(UIMSG_CHECKSUM,Item->Name);

        // Close only corrupt REV volumes here. We'll close and rename corrupt
        // RAR volumes later, if we'll know that recovery is possible.
        if (I>=DataCount)
        {
          Item->f->Close();
          Item->f=NULL;
          FoundRecVolumes--;
        }
      }
    }
    if (I<DataCount && (Item->f==NULL || !Item->Valid))
      MissingVolumes++;
  }

  uiMsg(UIMSG_RECVOLMISSING,MissingVolumes);

  if (MissingVolumes==0)
  {
    uiMsg(UIERROR_RECVOLALLEXIST);
    return false;
  }

  if (MissingVolumes>FoundRecVolumes)
  {
    uiMsg(UIERROR_RECVOLFOUND,FoundRecVolumes); // Intentionally not displayed in console mode.
    uiMsg(UIERROR_RECVOLCANNOTFIX);
    return false;
  }

  uiMsg(UIMSG_RECONSTRUCTING);

  // Create missing and rename bad volumes.
  uint64 MaxVolSize=0;
  for (uint I=0;I<DataCount;I++)
  {
    RecVolItem *Item=&RecItems[I];
    if (Item->FileSize>MaxVolSize)
      MaxVolSize=Item->FileSize;
    if (Item->f!=NULL && !Item->Valid)
    {
      Item->f->Close();

      wchar NewName[NM];
      wcscpy(NewName,Item->Name);
      wcscat(NewName,L".bad");

      uiMsg(UIMSG_BADARCHIVE,Item->Name);
      uiMsg(UIMSG_RENAMING,Item->Name,NewName);
      RenameFile(Item->Name,NewName);
      delete Item->f;
      Item->f=NULL;
    }

    if (Item->New=(Item->f==NULL))
    {
      wcsncpyz(Item->Name,FirstVolName,ASIZE(Item->Name));
      uiMsg(UIMSG_CREATING,Item->Name);
      uiMsg(UIEVENT_NEWARCHIVE,Item->Name);
      File *NewVol=new File;
      bool UserReject;
      if (!FileCreate(Cmd,NewVol,Item->Name,ASIZE(Item->Name),&UserReject))
      {
        if (!UserReject)
          ErrHandler.CreateErrorMsg(Item->Name);
        ErrHandler.Exit(UserReject ? RARX_USERBREAK:RARX_CREATE);
      }
      NewVol->Prealloc(Item->FileSize);
      Item->f=NewVol;
      Item->New=true;
    }
    NextVolumeName(FirstVolName,ASIZE(FirstVolName),false);
  }


  int64 ProcessedSize=0;
#ifndef GUI
  int LastPercent=-1;
  mprintf(L"     ");
#endif

  // Even though we already preliminary calculated missing volume number,
  // let's do it again now, when we have the final and exact information.
  MissingVolumes=0;

  ValidFlags=new bool[TotalCount];
  for (uint I=0;I<TotalCount;I++)
  {
    ValidFlags[I]=RecItems[I].f!=NULL && !RecItems[I].New;
    if (I<DataCount && !ValidFlags[I])
      MissingVolumes++;
  }

  // Size of per file buffer.
  RecBufferSize=TotalBufferSize/MissingVolumes;
  if ((RecBufferSize&1)==1) // Must be even for our RS16 codec.
    RecBufferSize--;
#ifdef USE_SSE
  RecBufferSize&=~(SSE_ALIGNMENT-1); // Align for SSE.
#endif

  uint *Data=new uint[TotalCount];

  RSCoder16 RS;
  if (!RS.Init(DataCount,RecCount,ValidFlags))
    return false; // Should not happen, we check parameter validity above.

  RealReadBuffer=new byte[RecBufferSize+SSE_ALIGNMENT];
  byte *ReadBuf=(byte *)ALIGN_VALUE(RealReadBuffer,SSE_ALIGNMENT);

  while (true)
  {
    Wait();

    int MaxRead=0;
    for (uint I=0,J=DataCount;I<DataCount;I++)
    {
      uint VolNum=I;
      if (!ValidFlags[I]) // If next RAR volume is missing or invalid.
      {
        while (!ValidFlags[J]) // Find next valid REV volume.
          J++;
        VolNum=J++; // Use next valid REV volume data instead of RAR.
      }
      RecVolItem *Item=RecItems+VolNum;

      byte *B=&ReadBuf[0];
      int ReadSize=0;
      if (Item->f!=NULL && !Item->New)
        ReadSize=Item->f->Read(B,RecBufferSize);
      if (ReadSize!=RecBufferSize)
        memset(B+ReadSize,0,RecBufferSize-ReadSize);
      if (ReadSize>MaxRead)
        MaxRead=ReadSize;

      // We can have volumes of different size. Let's use data chunk
      // for largest volume size.
      uint DataToProcess=(uint)Min(RecBufferSize,MaxVolSize-ProcessedSize);
      ProcessRS(Cmd,I,B,DataToProcess,false);
    }
    if (MaxRead==0)
      break;

    for (uint I=0,J=0;I<DataCount;I++)
      if (!ValidFlags[I])
      {
        RecVolItem *Item=RecItems+I;
        size_t WriteSize=(size_t)Min(MaxRead,Item->FileSize);
        Item->f->Write(Buf+(J++)*RecBufferSize,WriteSize);
        Item->FileSize-=WriteSize;
      }

    int CurPercent=ToPercent(ProcessedSize,RecFileSize);
    if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
    {
      uiProcessProgress("RV",ProcessedSize,RecFileSize);
      LastPercent=CurPercent;
    }
    ProcessedSize+=MaxRead;
  }

  for (uint I=0;I<TotalCount;I++)
    if (RecItems[I].f!=NULL)
      RecItems[I].f->Close();

  delete[] ValidFlags;
  delete[] Data;
#if !defined(GUI) && !defined(SILENT)
  if (!Cmd->DisablePercentage)
    mprintf(L"\b\b\b\b100%%");
  if (!Silent && !Cmd->DisableDone)
    mprintf(St(MDone));
#endif
  return true;
}
Example #9
0
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,const wchar *NameW,bool Silent)
{
  char ArcName[NM];
  wchar ArcNameW[NM];
  strcpy(ArcName,Name);
  wcscpy(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,"*.*");

    if (*ArcNameW!=0)
    {
      wchar *ExtW=GetExt(ArcNameW);
      for (int DigitGroup=0;ExtW>ArcNameW && DigitGroup<3;ExtW--)
        if (!IsDigit(*ExtW))
          if (IsDigit(*(ExtW-1)) && (*ExtW=='_' || DigitGroup<2))
            DigitGroup++;
          else
            if (DigitGroup<2)
            {
              NewStyle=true;
              break;
            }
      while (IsDigit(*ExtW) && ExtW>ArcNameW+1)
        ExtW--;
      wcscpy(ExtW,L"*.*");
    }

    FindFile Find;
    Find.SetMask(ArcName);
    Find.SetMaskW(ArcNameW);
    FindData fd;
    while (Find.Next(&fd))
    {
      Archive Arc(Cmd);
      if (Arc.WOpen(fd.Name,fd.NameW) && Arc.IsArchive(true))
      {
        strcpy(ArcName,fd.Name);
        wcscpy(ArcNameW,fd.NameW);
        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)!=0;
  Arc.Close();

  char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
  char RecVolMask[NM];
  strcpy(RecVolMask,ArcName);
  size_t BaseNamePartLength=VolNumStart-ArcName;
  strcpy(RecVolMask+BaseNamePartLength,"*.rev");

  wchar RecVolMaskW[NM];
  size_t BaseNamePartLengthW=0;
  *RecVolMaskW=0;
  if (*ArcNameW!=0)
  {
    wchar *VolNumStartW=VolNameToFirstName(ArcNameW,ArcNameW,NewNumbering);
    wcscpy(RecVolMaskW,ArcNameW);
    BaseNamePartLengthW=VolNumStartW-ArcNameW;
    wcscpy(RecVolMaskW+BaseNamePartLengthW,L"*.rev");
  }


#ifndef SILENT
  int64 RecFileSize=0;
#endif

  // We cannot display "Calculating CRC..." message here, because we do not
  // know if we'll find any recovery volumes. We'll display it after finding
  // the first recovery volume.
  bool CalcCRCMessageDone=false;

  FindFile Find;
  Find.SetMask(RecVolMask);
  Find.SetMaskW(RecVolMaskW);
  FindData RecData;
  int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
  char PrevName[NM];
  wchar PrevNameW[NM];
  while (Find.Next(&RecData))
  {
    char *CurName=RecData.Name;
    wchar *CurNameW=RecData.NameW;
    int P[3];
    if (!RevName && !NewStyle)
    {
      NewStyle=true;

      char *Dot=GetExt(CurName);
      if (Dot!=NULL)
      {
        int LineCount=0;
        Dot--;
        while (Dot>CurName && *Dot!='.')
        {
          if (*Dot=='_')
            LineCount++;
          Dot--;
        }
        if (LineCount==2)
          NewStyle=false;
      }

      wchar *DotW=GetExt(CurNameW);
      if (DotW!=NULL)
      {
        int LineCount=0;
        DotW--;
        while (DotW>CurNameW && *DotW!='.')
        {
          if (*DotW=='_')
            LineCount++;
          DotW--;
        }
        if (LineCount==2)
          NewStyle=false;
      }
    }
    if (NewStyle)
    {
      if (!CalcCRCMessageDone)
      {
#ifndef SILENT
        mprintf(St(MCalcCRCAllVol));
#endif
        CalcCRCMessageDone=true;
      }

#ifndef SILENT
        mprintf("\r\n%s",CurName);
#endif

      File CurFile;
      CurFile.TOpen(CurName,CurNameW);
      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),CurName);
#endif
        continue;
      }
    }
    else
    {
      char *Dot=GetExt(CurName);
      if (Dot==NULL)
        continue;
      bool WrongParam=false;
      for (int I=0;I<ASIZE(P);I++)
      {
        do
        {
          Dot--;
        } while (IsDigit(*Dot) && Dot>=CurName+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),CurName,PrevName);
#endif
      return(false);
    }
    RecVolNumber=P[1];
    FileNumber=P[2];
    strcpy(PrevName,CurName);
    wcscpy(PrevNameW,CurNameW);
    File *NewFile=new File;
    NewFile->TOpen(CurName,CurNameW);
    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;
  wchar LastVolNameW[NM];
  *LastVolNameW=0;

  for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
  {
    Archive *NewFile=new Archive;
    bool ValidVolume=FileExist(ArcName,ArcNameW);
    if (ValidVolume)
    {
      NewFile->TOpen(ArcName,ArcNameW);
      ValidVolume=NewFile->IsArchive(false);
      if (ValidVolume)
      {
        while (NewFile->ReadHeader()!=0)
        {
          if (NewFile->GetHeaderType()==ENDARC_HEAD)
          {
#ifndef SILENT
            mprintf("\r\n%s",ArcName);
#endif
            if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 &&
                NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
            {
              ValidVolume=false;
#ifndef SILENT
              mprintf(St(MCRCFailed),ArcName);
#endif
            }
            break;
          }
          NewFile->SeekToNext();
        }
      }
      if (!ValidVolume)
      {
        NewFile->Close();
        char NewName[NM];
        strcpy(NewName,ArcName);
        strcat(NewName,".bad");

        wchar NewNameW[NM];
        wcscpy(NewNameW,ArcNameW);
        if (*NewNameW!=0)
          wcscat(NewNameW,L".bad");
#ifndef SILENT
        mprintf(St(MBadArc),ArcName);
        mprintf(St(MRenaming),ArcName,NewName);
#endif
        RenameFile(ArcName,ArcNameW,NewName,NewNameW);
      }
      NewFile->Seek(0,SEEK_SET);
    }
    if (!ValidVolume)
    {
      // It is important to return 'false' instead of aborting here,
      // so if we are called from extraction, we will be able to continue extracting.
      // It may happen if .rar and .rev are on read-only disks like CDs.
      if (!NewFile->Create(ArcName,ArcNameW))
      {
        // We need to display the title of operation before the error message,
        // to make clear for user that create error is related to recovery
        // volumes. This is why we cannot use WCreate call here. Title must be
        // before create error, not after that.
#ifndef SILENT
        mprintf(St(MReconstructing));
#endif
        ErrHandler.CreateErrorMsg(ArcName,ArcNameW);
        return false;
      }

      WriteFlags[CurArcNum]=true;
      MissingVolumes++;

      if (CurArcNum==FileNumber-1)
      {
        strcpy(LastVolName,ArcName);
        wcscpy(LastVolNameW,ArcNameW);
      }

#ifndef SILENT
      mprintf(St(MAbsNextVol),ArcName);
#endif
    }
    SrcFile[CurArcNum]=(File*)NewFile;
    NextVolumeName(ArcName,ArcNameW,ASIZE(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

  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
  // Size of per file buffer.
  size_t RecBufferSize=TotalBufferSize/TotalFiles;

#ifdef RAR_SMP
  uint ThreadNumber=Cmd->Threads;
  RSEncode rse[MaxPoolThreads];
  uint WaitHandles[MaxPoolThreads];
#else
  uint ThreadNumber=1;
  RSEncode rse[1];
#endif
  for (uint I=0;I<ThreadNumber;I++)
    rse[I].Init(RecVolNumber);

  while (true)
  {
    Wait();
    int MaxRead=0;
    for (int I=0;I<TotalFiles;I++)
      if (WriteFlags[I] || SrcFile[I]==NULL)
        memset(&Buf[I*RecBufferSize],0,RecBufferSize);
      else
      {
        int ReadSize=SrcFile[I]->Read(&Buf[I*RecBufferSize],RecBufferSize);
        if (ReadSize!=RecBufferSize)
          memset(&Buf[I*RecBufferSize+ReadSize],0,RecBufferSize-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


    int BlockStart=0;
    int BlockSize=MaxRead/ThreadNumber;
    if (BlockSize<0x100)
      BlockSize=MaxRead;
    uint CurThread=0;

    while (BlockStart<MaxRead)
    {
      // Last thread processes all left data including increasement from rounding error.
      if (CurThread==ThreadNumber-1)
        BlockSize=MaxRead-BlockStart;

      RSEncode *curenc=rse+CurThread;
      curenc->Buf=&Buf[0];
      curenc->BufStart=BlockStart;
      curenc->BufEnd=BlockStart+BlockSize;
      curenc->FileNumber=TotalFiles;
      curenc->RecBufferSize=RecBufferSize;
      curenc->Erasures=Erasures;
      curenc->EraSize=EraSize;

#ifdef RAR_SMP
      if (ThreadNumber>1)
      {
        uint Handle=RSThreadPool.Start(RSDecodeThread,(void*)curenc);
        WaitHandles[CurThread++]=Handle;
      }
      else
        curenc->DecodeBuf();
#else
      curenc->DecodeBuf();
#endif

      BlockStart+=BlockSize;
    }

#ifdef RAR_SMP
    if (CurThread>0)
      RSThreadPool.Wait(WaitHandles,CurThread);
#endif // RAR_SMP

    for (int I=0;I<FileNumber;I++)
      if (WriteFlags[I])
        SrcFile[I]->Write(&Buf[I*RecBufferSize],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!=0 || *LastVolNameW!=0)
  {
    // Truncate the last volume to its real size.
    Archive Arc(Cmd);
    if (Arc.Open(LastVolName,LastVolNameW,FMF_UPDATE) && 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);
}
Example #10
0
void PluginClass::GetOpenPluginInfo(struct OpenPluginInfo *Info)
{
  Info->StructSize=sizeof(*Info);
  Info->Flags=OPIF_USEFILTER|OPIF_USESORTGROUPS|OPIF_USEHIGHLIGHTING|
              OPIF_ADDDOTS|OPIF_COMPAREFATTIME;
  Info->HostFile=ArcName;
  Info->CurDir=CurDir;

  if (bGOPIFirstCall)
    ArcPlugin->GetFormatName(ArcPluginNumber,ArcPluginType,FormatName,DefExt);

  char NameTitle[NM];
  lstrcpyn(NameTitle,FSF.PointToName(ArcName),sizeof(NameTitle));

  {
    struct PanelInfo PInfo;
    if(::Info.Control((HANDLE)this,FCTL_GETPANELSHORTINFO,&PInfo))
    {     //TruncStr
      FSF.TruncPathStr(NameTitle,(PInfo.PanelRect.right-PInfo.PanelRect.left+1-(lstrlen(FormatName)+3+4)));
    }
  }

  FSF.sprintf(Title," %s:%s%s%s ",FormatName,NameTitle, *CurDir ? "\\" : "", *CurDir ? CurDir : "");

  Info->PanelTitle=Title;

  if (bGOPIFirstCall || FarLangChanged())
  {
    FSF.sprintf(Format,GetMsg(MArcFormat),FormatName);

    memset(InfoLines,0,sizeof(InfoLines));
    FSF.sprintf(InfoLines[0].Text,GetMsg(MInfoTitle),FSF.PointToName(ArcName));
    InfoLines[0].Separator=TRUE;
    FSF.sprintf(InfoLines[1].Text,GetMsg(MInfoArchive));
    lstrcpy(InfoLines[1].Data,FormatName);

    if (ItemsInfo.UnpVer!=0)
      FSF.sprintf(InfoLines[1].Data+lstrlen(InfoLines[1].Data)," %d.%d",
              ItemsInfo.UnpVer/256,ItemsInfo.UnpVer%256);

    if (*ItemsInfo.HostOS)
      FSF.sprintf(InfoLines[1].Data+lstrlen(InfoLines[1].Data),"/%s",ItemsInfo.HostOS);

    lstrcpy(InfoLines[2].Text,GetMsg(MInfoArcType));

    if (ItemsInfo.Solid)
      lstrcpy(InfoLines[2].Data,GetMsg(MInfoSolid));

    if (CurArcInfo.SFXSize)
    {
      if (*InfoLines[2].Data)
        lstrcat(InfoLines[2].Data," ");
      lstrcat(InfoLines[2].Data,GetMsg(MInfoSFX));
    }

    if (CurArcInfo.Flags & AF_HDRENCRYPTED)
    {
      if (*InfoLines[2].Data)
        lstrcat(InfoLines[2].Data," ");
      lstrcat(InfoLines[2].Data,GetMsg(MInfoHdrEncrypted));
    }

    if (CurArcInfo.Volume)
    {
      if (*InfoLines[2].Data)
        lstrcat(InfoLines[2].Data," ");
      lstrcat(InfoLines[2].Data,GetMsg(MInfoVolume));
    }

    if (*InfoLines[2].Data==0)
      lstrcpy(InfoLines[2].Data,GetMsg(MInfoNormal));

    lstrcpy(InfoLines[3].Text,GetMsg(MInfoArcComment));
    lstrcpy(InfoLines[3].Data,CurArcInfo.Comment ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[4].Text,GetMsg(MInfoFileComments));
    lstrcpy(InfoLines[4].Data,ItemsInfo.Comment ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[5].Text,GetMsg(MInfoPasswords));
    lstrcpy(InfoLines[5].Data,ItemsInfo.Encrypted ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[6].Text,GetMsg(MInfoRecovery));
    lstrcpy(InfoLines[6].Data,CurArcInfo.Recovery ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[7].Text,GetMsg(MInfoLock));
    lstrcpy(InfoLines[7].Data,CurArcInfo.Lock ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[8].Text,GetMsg(MInfoAuthVer));
    lstrcpy(InfoLines[8].Data,(CurArcInfo.Flags & AF_AVPRESENT) ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent));
    lstrcpy(InfoLines[9].Text,GetMsg(MInfoDict));

    if (ItemsInfo.DictSize==0)
      lstrcpy(InfoLines[9].Data,"???");
    else
      FSF.sprintf(InfoLines[9].Data,"%d %s",ItemsInfo.DictSize,GetMsg(MInfoDictKb));

    lstrcpy(InfoLines[10].Text,GetMsg(MInfoChapters));
    if(CurArcInfo.Chapters)
      //FSF.sprintf(InfoLines[10].Data,"%d/%d",ItemsInfo.Chapter,CurArcInfo.Chapters);
      FSF.sprintf(InfoLines[10].Data,"%d",CurArcInfo.Chapters);
    else
      lstrcpy(InfoLines[10].Data,GetMsg(MInfoAbsent));

    lstrcpy(InfoLines[11].Text,GetMsg(MInfoTotalFiles));
    FSF.sprintf(InfoLines[11].Data,"%d",ArcDataCount);
    lstrcpy(InfoLines[12].Text,GetMsg(MInfoTotalSize));
    InsertCommas(TotalSize,InfoLines[12].Data);
    lstrcpy(InfoLines[13].Text,GetMsg(MInfoPackedSize));
    InsertCommas(PackedSize,InfoLines[13].Data);
    lstrcpy(InfoLines[14].Text,GetMsg(MInfoRatio));
    FSF.sprintf(InfoLines[14].Data,"%d%%",ToPercent(PackedSize,TotalSize));

    memset(&KeyBar,0,sizeof(KeyBar));
    KeyBar.ShiftTitles[1-1]=(char*)"";
    KeyBar.AltTitles[6-1]=(char*)GetMsg(MAltF6);
    KeyBar.AltShiftTitles[9-1]=(char*)GetMsg(MAltShiftF9);
  }

  Info->Format=Format;
  Info->KeyBar=&KeyBar;
  Info->InfoLines=InfoLines;
  Info->InfoLinesNumber=ARRAYSIZE(InfoLines);

  lstrcpy(DescrFilesString,Opt.DescriptionNames);
  size_t DescrFilesNumber=0;
  char *NamePtr=DescrFilesString;

  while (DescrFilesNumber<ARRAYSIZE(DescrFiles))
  {
    while (__isspace(*NamePtr))
      NamePtr++;
    if (*NamePtr==0)
      break;
    DescrFiles[DescrFilesNumber++]=NamePtr;
    if ((NamePtr=strchr(NamePtr,','))==NULL)
      break;
    *(NamePtr++)=0;
  }

  Info->DescrFiles=DescrFiles;

  if (!Opt.ReadDescriptions || DizPresent)
    Info->DescrFilesNumber=0;
  else
    Info->DescrFilesNumber=(int)DescrFilesNumber;

  bGOPIFirstCall = false;
}
Example #11
0
void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize)
{
  int CurPercent=ToPercent(CurSize,TotalSize);
  mprintf(L"\b\b\b\b%3d%%",CurPercent);
}
Example #12
0
void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize)
{
  int CurPercent=ToPercent(CurSize,TotalSize);
  mprintf(L"\b\b\b\b%3d%%",CurPercent);
}
Example #13
0
/****************************************
    Callback called from GetFiles and PutFiles each time whole buffer
    sended or received to refresh state of copy progress
    Can be called in any plugin state (quite, not show, etc)
 ****************************************/
BOOL TrafficInformation::Callback(int Size)
{
	double tmDiff;
	DWORD     tm;
	time_t        tmt;
	char          str[MAX_PATH];
	double        TotalPercent,db;
	GET_TIME(tm);
	tmDiff = Abs(CMP_TIME(tm,LastTime));
	tmt = time(NULL);
	FileSize     += Size;
	FullFileSize  = Max(FileSize,FullFileSize);

	if(Size && FTP_Info->CheckForEsc(FALSE,FALSE))
	{
		Log(("User cancel"));
		return FALSE;
	}

	if(Size && tmDiff*1000 < FTP_Info->GetOpt()->IdleShowPeriod)
		return TRUE;

	memmove(&LastTime,&tm,sizeof(LastTime));
	TotalPercent = ToPercent(TotalSz(),TotalFullSize);

	//Avg
	if(tmDiff > 0)
	{
		AvCps[0] = AvCps[1];
		AvCps[1] = AvCps[2];
		AvCps[2] = (FileSize - LastSize) / tmDiff;
	}

	LastSize = FileSize;
	//Cur
	db = ((double)tmt-FileStartTime-FileWaitTime);

	if(db > 0)
		Cps = FileSize / db;
	else
		Cps = 0;

	//Total
	db = ((double)tmt-TotalStartTime-TotalWaitTime);

	if(db > 0)
		TotalCps = (TotalSize+FileSize) / db;
	else
		TotalCps = 0;

//Show QUIET progressing
	if(!ShowStatus)
	{
		_snprintf(str,ARRAYSIZE(str),
		         "{%2.1lf%%} %s: %.26s",
		         TotalPercent,
		         FTP_Info->GetMsg(TitleMsg),
		         FTP_Info->PointToName(SrcFileName));
		FTP_Info->IdleMessage(str,FTP_Info->GetOpt()->ProcessColor);
		return TRUE;
	}

//Window caption
	if(FTP_Info->FtpGetRetryCount())
		_snprintf(str,ARRAYSIZE(str),"%d: {%2.1lf%%} %s - Far",
		         FTP_Info->FtpGetRetryCount(), TotalPercent,
		         FTP_Info->GetMsg(TitleMsg));
	else
		_snprintf(str,ARRAYSIZE(str),"{%2.1lf%%} %s - Far",
		         TotalPercent,FTP_Info->GetMsg(TitleMsg));

	if(StrCmp(str,ConsoleTitle,-1,TRUE) != 0)
	{
		if(FTP_Info->WinVer->dwPlatformId != VER_PLATFORM_WIN32_NT)
			OemToChar(str,str);

		SetConsoleTitle(str);
		StrCpy(ConsoleTitle,str,ARRAYSIZE(ConsoleTitle));
	}

//Mark CMD window invisible
	FTP_Info->FtpCmdBlock(TRUE);
//Show message
	LPCSTR MsgItems[MAX_TRAF_LINES+1];
	DrawInfos(tmt);

	if(FTP_Info->FtpGetRetryCount())
		_snprintf(str,ARRAYSIZE(str),"%d: %s",FTP_Info->FtpGetRetryCount(),FTP_Info->GetMsg(TitleMsg));
	else
		StrCpy(str,FTP_Info->GetMsg(TitleMsg),ARRAYSIZE(str));

	MsgItems[0] = str;
	int n;

	for(n = 0; n < LineCount; n++)
		MsgItems[n+1] = Lines[n];

	FTP_Info->FMessage(FMSG_LEFTALIGN, NULL,
	                   (LPCSTR *)MsgItems, LineCount+1, 0);
	return TRUE;
}
Example #14
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);
}
Example #15
0
/****************************************
   TrafficInformation
 ****************************************/
void TrafficInformation::DrawInfo(InfoItem* it,time_t tm)
{
	static char str[MAX_PATH+1];
	double db;
	int    cn;
	time_t tmp;
	struct tm *ltm;
	int    len;

	switch(it->Type)
	{
			//00 " " ---- Space
		case 00:
			break;
			//01 "SrcPathname" ---- Source filename
		case 01: FTP_Info->StrCpy(str,SrcFileName,ARRAYSIZE(str));
			break;
			//02 "SrcPath",
		case 02: FTP_Info->StrCpy(str,SrcFileName,ARRAYSIZE(str));
			FTP_Info->PointToName(str)[0] = 0;
			break;
			//03 "SrcName",
		case 03: FTP_Info->StrCpy(str,FTP_Info->PointToName(SrcFileName),ARRAYSIZE(str));
			break;
			//04 "DestPathname" ---- Target filename
		case 04: FTP_Info->StrCpy(str,DestFileName,ARRAYSIZE(str));
			break;
			//05 "DestPath",
		case 05: FTP_Info->StrCpy(str,DestFileName,ARRAYSIZE(str));
			FTP_Info->PointToName(str)[0] = 0;
			break;
			//06 "DestName",
		case 06: FTP_Info->StrCpy(str,FTP_Info->PointToName(DestFileName),ARRAYSIZE(str));
			break;
			//07 "CurSize" ---- Current processed size
		case 07: FTP_Info->FDigit(str,CurrentSz(),-1);
			break;
			//08 "CurESize" ---- Full size of current file
			//09 "CurFSize",
		case  8:
		case  9: FTP_Info->FDigit(str,FullFileSize,-1);
			break;
			//10 "CurRSize" ---- Remain size of current file
		case 10: FTP_Info->FDigit(str,CurrentRemain(),-1);
			break;
			//11 "CurTime" ---- Time from start of current file
		case 11: cn = (int)(tm - FileStartTime);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//12 "CurFTime" ---- Full time to process current file
		case 12: db = Cps;

			if(db > 0)
				cn = (int)(CurrentDoRemain() / db);
			else
				cn = 0;

			cn = Max(cn,0);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//13 "CurRTime" ---- Remain time to process current file
		case 13: db = Cps;

			if(db > 0)
				cn = (int)(CurrentRemain() / db);
			else
				cn = 0;

			cn = Max(cn,0);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//14 "CurETime" ---- End time to process current file
		case 14: db = Cps;

			if(db > 0)
				tmp = tm + (time_t)(CurrentRemain() / db);
			else
				tmp = tm;

			tmp = Max(tmp,tm);
			ltm = Localtime(&tmp);
			StrTTime(str,ltm);
			break;
			//15 "CurEDate" ---- End date to process current file
		case 15: db = Cps;

			if(db > 0)
				tmp = tm + (time_t)(CurrentRemain() / db);
			else
				tmp = tm;

			tmp = Max(tmp,tm);
			ltm = Localtime(&tmp);
			StrYTime(str,ltm);
			break;
			//16 "TotSize" ---- Current processed size
		case 16: FTP_Info->FDigit(str,TotalSz(),-1);
			break;
			//17 "TotESize" ---- Full size of current file
			//18 "TotFSize",
		case 17:
		case 18: FTP_Info->FDigit(str,TotalFullSize,-1);
			break;
			//19 "TotRSize" ---- Remain size of current file
		case 19: FTP_Info->FDigit(str,TotalRemain(),-1);
			break;
			//20 "TotTime" ---- Time from start of current file
		case 20: cn = (int)(tm - TotalStartTime);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//21 "TotFTime" ---- Full time to process current file
		case 21: db = (AvCps[0] + AvCps[1] + AvCps[2])/3;

			if(db > 0)
				cn = (int)(TotalDoRemain() / db);
			else
				cn = 0;

			cn = Max(cn,0);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//22 "TotRTime" ----- Remain time to process current file
		case 22: db = (AvCps[0] + AvCps[1] + AvCps[2])/3;

			if(db > 0)
				cn = (int)(TotalRemain() / db);
			else
				cn = 0;

			cn = Max(cn,0);
			_snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60);
			break;
			//23 "TotETime" ---- End time to process all files
		case 23: db = TotalCps;

			if(db > 0)
				tmp = tm + (time_t)(TotalRemain() / db);
			else
				tmp = tm;

			ltm = Localtime(&tmp);
			StrTTime(str,ltm);
			break;
			//24 "TotEDate" ----- End date to process current file
		case 24: db = TotalCps;

			if(db > 0)
				tmp = tm + (time_t)(TotalRemain() / db);
			else
				tmp = tm;

			ltm = Localtime(&tmp);
			StrYTime(str,ltm);
			break;
			//25 "CurCPS"   ----- CP of current file
		case 25: FTP_Info->FCps(str,Cps);
			break;
			//26 "CPS"      -----  Summary CPS
		case 26: FTP_Info->FCps(str,(AvCps[0] + AvCps[1] + AvCps[2])/3);
			break;
			//27 "TotCPS"   ----- Total CPS
		case 27: FTP_Info->FCps(str,TotalCps);
			break;
			//28 "Progress" ----- Current progress bar
			//42 "Pg"       ----- ALIAS `Progress`
		case 42:
		case 28: PPercent(str,0,it->Size-1,(int)ToPercent(CurrentSz(),FullFileSize));
			break;
			//29 "FProgress"----- Total progress bar
			//43 "FPg"      ----- ALIAS `FProgress`
		case 43:
		case 29: PPercent(str,0,it->Size-1,(int)ToPercent(TotalSz(),TotalFullSize));
			break;
			//40 "Pc"       ----- ALIAS `Percent`
			//30 "PerCent"  ----- Current "99.9%" percent
		case 40:
		case 30: db = ToPercent(CurrentSz(),FullFileSize);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%2.1lf%%",db);

			break;
			//41 "FPc" ---- ALIAS `FPercent`
			//31 "FPerCent" ----- Total "99.9%" percent
		case 41:
		case 31: db = ToPercent(TotalSz(),TotalFullSize);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%2.1lf%%",db);

			break;
			//32 "Cn" ---- Complete count
		case 32: FTP_Info->FDigit(str,TotalComplete,-1);
			break;
			//33 "CnSkip" ---- Skipped count
		case 33: FTP_Info->FDigit(str,TotalSkipped,-1);
			break;
			//34 "CnR" ---- Remain count
		case 34: FTP_Info->FDigit(str,TotalFiles-TotalComplete-TotalSkipped,-1);
			break;
			//35 "CnF" ---- Count
		case 35: FTP_Info->FDigit(str,TotalFiles,-1);
			break;
			//36 "CurPc" ---- Current percent
		case 36: db = ToPercent(TotalComplete,TotalFiles);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%2.1lf%%",db);

			break;
			//37 "SkipPc" ---- Skipped percent
		case 37: db = ToPercent(TotalSkipped,TotalFiles);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%2.1lf%%",db);

			break;
			//38 "CurPg"     ---- Current percent progress
		case 38: PPercent(str,0,it->Size-1,(int)ToPercent(TotalComplete,TotalFiles));
			break;
			//39 "SkipPg"    ---- Skipped percent progress
		case 39: PPercent(str,0,it->Size-1,(int)ToPercent(TotalSkipped,TotalFiles));
			break;
			//44 "CurCPS4"   ----- CP of current file
		case 44: FCps4(str,Cps);
			break;
			//45 "CPS4"      -----  Summary CPS
		case 45: FCps4(str,(AvCps[0] + AvCps[1] + AvCps[2])/3);
			break;
			//46 "TotCPS4"   ----- Total CPS
		case 46: FCps4(str,TotalCps);
			break;
			//47 "IPc"       ----- Current "99%" percent
		case 47: db = ToPercent(CurrentSz(),FullFileSize);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%d%%",(int)db);

			break;
			//48 "IFPc"      ----- Total "99%" percent
		case 48: db = ToPercent(TotalSz(),TotalFullSize);

			if(((int)db) == 100)
				FTP_Info->StrCpy(str,"100%",-1);
			else
				sprintf(str,"%d%%",(int)db);

			break;
	}

	if(it->Type)
	{
		len = static_cast<int>(strlen(str));

		if(!it->Size && it->Align == tCenter)
			it->Pos -= len/2;

		if(!it->Size)
			it->Size = len;

		if(len > it->Size && it->Align == tCenter)
			it->Align = tLeft;

		if(it->Pos+it->Size > MAX_TRAF_WIDTH)
			return;

		if(len > it->Size)
		{
			if(it->Align == tLeft)
			{
				memmove(Lines[it->Line]+it->Pos,str+len-it->Size,it->Size);
				Lines[it->Line][it->Pos] = FAR_LEFT_CHAR;
			}
			else
			{
				memmove(Lines[it->Line]+it->Pos,str,it->Size);
				Lines[it->Line][it->Pos+it->Size] = FAR_RIGHT_CHAR;
			}
		}
		else
		{
			//Clear
			if(it->Align != tCenter)
				memset(Lines[it->Line]+it->Pos,it->Fill,it->Size);

			//Draw
			if(it->Align == tLeft)
				memmove(Lines[it->Line]+it->Pos, str, len);
			else if(it->Align == tRight)
				memmove(Lines[it->Line]+it->Pos + it->Size - len, str, len);
			else
				memmove(Lines[it->Line]+it->Pos + it->Size/2 - len/2, str, len);
		}
	}
	else
	{
		memset(Lines[it->Line]+it->Pos,it->Fill,it->Size);
	}
}
Example #16
0
void QuickView::DisplayObject()
{
	if (Flags.Check(FSCROBJ_ISREDRAWING))
		return;

	Flags.Set(FSCROBJ_ISREDRAWING);
	FARString strTitle;

	if (!QView && !ProcessingPluginCommand)
		CtrlObject->Cp()->GetAnotherPanel(this)->UpdateViewPanel();

	if (QView)
		QView->SetPosition(X1+1,Y1+1,X2-1,Y2-3);

	Box(X1,Y1,X2,Y2,COL_PANELBOX,DOUBLE_BOX);
	SetScreen(X1+1,Y1+1,X2-1,Y2-1,L' ',COL_PANELTEXT);
	SetColor(Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE);
	GetTitle(strTitle);

	if (!strTitle.IsEmpty())
	{
		GotoXY(X1+(X2-X1+1-(int)strTitle.GetLength())/2,Y1);
		Text(strTitle);
	}

	DrawSeparator(Y2-2);
	SetColor(COL_PANELTEXT);
	GotoXY(X1+1,Y2-1);
	FS<<fmt::LeftAlign()<<fmt::Width(X2-X1-1)<<fmt::Precision(X2-X1-1)<<PointToName(strCurFileName);

	if (!strCurFileType.IsEmpty())
	{
		FARString strTypeText=L" ";
		strTypeText+=strCurFileType;
		strTypeText+=L" ";
		TruncStr(strTypeText,X2-X1-1);
		SetColor(COL_PANELSELECTEDINFO);
		GotoXY(X1+(X2-X1+1-(int)strTypeText.GetLength())/2,Y2-2);
		Text(strTypeText);
	}

	if (Directory)
	{
		FormatString FString;
		FString<<MSG(MQuickViewFolder)<<L" \""<<strCurFileName<<L"\"";
		SetColor(COL_PANELTEXT);
		GotoXY(X1+2,Y1+2);
		PrintText(FString);

		/*if ((apiGetFileAttributes(strCurFileName)&FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT)
		{
			FARString strJuncName;
			DWORD ReparseTag=0;

			if (GetReparsePointInfo(strCurFileName, strJuncName,&ReparseTag))
			{
				int ID_Msg=MQuickViewJunction;

				if (ReparseTag==IO_REPARSE_TAG_MOUNT_POINT)
				{
					if (IsLocalVolumeRootPath(strJuncName))
					{
						ID_Msg=MQuickViewVolMount;
					}
				}
				else if (ReparseTag==IO_REPARSE_TAG_SYMLINK)
				{
					ID_Msg=MQuickViewSymlink;
				}

				//"\??\D:\Junc\Src\"
				NormalizeSymlinkName(strJuncName);
				TruncPathStr(strJuncName,X2-X1-1-StrLength(MSG(ID_Msg)));
				FString.Clear();
				FString<<MSG(ID_Msg)<<L" \""<<strJuncName<<L"\"";
				SetColor(COL_PANELTEXT);
				GotoXY(X1+2,Y1+3);
				PrintText(FString);
			}
		}*/

		if (Directory==1 || Directory==4)
		{
			GotoXY(X1+2,Y1+4);
			PrintText(MSG(MQuickViewContains));
			GotoXY(X1+2,Y1+6);
			PrintText(MSG(MQuickViewFolders));
			SetColor(COL_PANELINFOTEXT);
			FString.Clear();
			FString<<DirCount;
			PrintText(FString);
			SetColor(COL_PANELTEXT);
			GotoXY(X1+2,Y1+7);
			PrintText(MSG(MQuickViewFiles));
			SetColor(COL_PANELINFOTEXT);
			FString.Clear();
			FString<<FileCount;
			PrintText(FString);
			SetColor(COL_PANELTEXT);
			GotoXY(X1+2,Y1+8);
			PrintText(MSG(MQuickViewBytes));
			SetColor(COL_PANELINFOTEXT);
			FARString strSize;
			InsertCommas(FileSize,strSize);
			PrintText(strSize);
			SetColor(COL_PANELTEXT);
			GotoXY(X1+2,Y1+9);
			PrintText(MSG(MQuickViewCompressed));
			SetColor(COL_PANELINFOTEXT);
			InsertCommas(CompressedFileSize,strSize);
			PrintText(strSize);
			SetColor(COL_PANELTEXT);
			GotoXY(X1+2,Y1+10);
			PrintText(MSG(MQuickViewRatio));
			SetColor(COL_PANELINFOTEXT);
			FString.Clear();
			FString<<ToPercent64(CompressedFileSize,FileSize)<<L"%";
			PrintText(FString);

			if (Directory!=4 && RealFileSize>=CompressedFileSize)
			{
				SetColor(COL_PANELTEXT);
				GotoXY(X1+2,Y1+12);
				PrintText(MSG(MQuickViewCluster));
				SetColor(COL_PANELINFOTEXT);
				FARString strSize;
				InsertCommas(ClusterSize,strSize);
				PrintText(strSize);
				SetColor(COL_PANELTEXT);
				GotoXY(X1+2,Y1+13);
				PrintText(MSG(MQuickViewRealSize));
				SetColor(COL_PANELINFOTEXT);
				InsertCommas(RealFileSize,strSize);
				PrintText(strSize);
				SetColor(COL_PANELTEXT);
				GotoXY(X1+2,Y1+14);
				PrintText(MSG(MQuickViewSlack));
				SetColor(COL_PANELINFOTEXT);
				InsertCommas(RealFileSize-CompressedFileSize,strSize);
				uint64_t Size1=RealFileSize-CompressedFileSize;
				uint64_t Size2=RealFileSize;

				while ((Size2 >> 32) )
				{
					Size1=Size1>>1;
					Size2=Size2>>1;
				}

				FString.Clear();
				FString<<strSize<<L" ("<<ToPercent((DWORD)Size1, (DWORD)Size2)<<L"%)";
				PrintText(FString);
			}
		}