Beispiel #1
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);
}
Beispiel #2
0
/*
* Inspired from llink (by lundman) which in turn was loosely based on
* patches from XBMC (by elupus).
*/
int ComprDataIO::UnpReadSeek(char *file, uint64_t offset)
{
	uint64_t OldPos;
	uint64_t HeadSize;
	Archive *SrcArc = (Archive *)SrcFile;

	if (!SrcFile->IsOpened()) {
		return(-1);
	}

	HeadSize = SrcArc->Tell() - CurUnpRead;

#ifdef DEBUG
	printf("\n%s: Seek begin, HeadSize=%d\n", __func__, HeadSize);
	printf("%s: offset=%llu, ", __func__, offset);
	printf("readpos=%llu, ", ReadPos);
	printf("diff=%llu, ", offset - ReadPos);
	printf("tell=%llu, ", SrcArc->Tell());
	printf("CurUnpRead=%llu\n", CurUnpRead);
#endif

	/* Dumb backward seek, reset to beginning and forward seek */
	if (offset < ReadPos) {
#ifdef DEBUG
		printf("Seeking backwards\n");
#endif
		SrcArc->Close();
		SrcArc->Open(SrcArc->FirstVolumeName, SrcArc->FirstVolumeNameW);

		if (SrcArc->GetHeaderType() != FILE_HEAD)
			SrcArc->SearchBlock(FILE_HEAD);
		do {
#ifdef DEBUG
			printf("File: %s, ", SrcArc->NewLhd.FileName);
			printf("packsize=%llu, ", SrcArc->NewLhd.FullPackSize);
			printf("method=%x\n", SrcArc->NewLhd.Method);
#endif
			/* XXX: fix unicode */
			if (_stricmp(SrcArc->NewLhd.FileName, file) == 0){
				SVP_LogMsg3(" ComprDataIO::UnpReadSeek match %s %s | %s ", file , SrcArc->FileName,  CStringA(SrcArc->FileNameW));
				//strcpy(SrcArc->FileName ,  CStringA(SrcArc->FileNameW));
				break;
			}
			//if (strcasecmp(SrcArc->NewLhd.FileName, file) == 0)
			//	break;
		} while (SrcArc->SearchBlock(FILE_HEAD));

		UnpVolume = true;
		SrcArc->Seek(SrcArc->CurBlockPos, SEEK_CUR);
		SrcArc->ReadHeader();

		CurUnpRead = ReadPos = 0;
	}

#ifdef DEBUG
	printf("%s: offset=%llu, ", __func__, offset);
	printf("readpos=%llu, ", ReadPos);
	printf("diff=%llu, ", offset - ReadPos);
	printf("tell=%llu, ", SrcArc->Tell());
	printf("CurUnpRead=%llu\n", CurUnpRead);
#endif

	/* Forward seek to correct volume */
	if (offset > ReadPos + SrcArc->NewLhd.FullPackSize - CurUnpRead) {
#ifdef DEBUG
		printf("%s: Seeking forward, ", __func__);
		printf("FullPackSize=%llu\n", SrcArc->NewLhd.FullPackSize);
#endif
		OldPos = ReadPos;
		ReadPos -= CurUnpRead;

		for (;;) {
			ReadPos += SrcArc->NewLhd.FullPackSize;

#ifdef DEBUG
			printf("%s: New readpos=%llu, ", __func__, ReadPos);
			printf("offset=%llu\n", offset);
#endif
			if (ReadPos >= offset) {	
				ReadPos -= SrcArc->NewLhd.FullPackSize;
#ifdef DEBUG
				printf("%s: offset reached\n", __func__);
#endif
				break;
			}
			if (!MergeArchive(*SrcArc, this, true, CurrentCommand)) {
				NextVolumeMissing = true;
#ifdef DEBUG
				printf("%s: volume missing\n", __func__);
#endif
				return (-1);
			}
		}
	}
	else {
		ReadPos -= CurUnpRead;
	}

#ifdef DEBUG
	printf("%s: offset=%llu, ", __func__, offset);
	printf("readpos=%llu, ", ReadPos);
	printf("diff=%llu, ", offset - ReadPos);
	printf("tell=%llu, ", SrcArc->Tell());
	printf("CurUnpRead=%llu\n", CurUnpRead);
#endif

	/* Absolute number of bytes read */
	CurUnpRead = offset - ReadPos;
	ReadPos += CurUnpRead;
	UnpPackedSize = SrcArc->NewLhd.FullPackSize - CurUnpRead;

	SrcFile->Seek(CurUnpRead + HeadSize, SEEK_SET);

#ifdef DEBUG
	printf("%s: offset=%llu, ", __func__, offset);
	printf("readpos=%llu, ", ReadPos);
	printf("diff=%llu, ", offset - ReadPos);
	printf("tell=%llu, ", SrcArc->Tell());
	printf("CurUnpRead=%llu, ", CurUnpRead);
	printf("UnpPackedSize=%llu\n", UnpPackedSize);
	printf("Seek complete\n\n");
#endif

	return (0);
}
Beispiel #3
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);
  wcscpy(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;

#if !defined(GUI) && !defined(SILENT)
  // In -vp mode we force the pause before next volume even if it is present
  // and even if we are on the hard disk. It is important when user does not
  // want to process partially downloaded volumes preliminary.
  if (Cmd->VolumePause && !AskNextVol(NextName,NextNameW))
    FailedOpen=true;
#endif

  if (!FailedOpen)
    while (!Arc.Open(NextName,NextNameW,0))
    {
      // 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);
        wcscpy(AltNextNameW,Arc.FileNameW);
        NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
        OldSchemeTested=true;
        if (Arc.Open(AltNextName,AltNextNameW,0))
        {
          strcpy(NextName,AltNextName);
          wcscpy(NextNameW,AltNextNameW);
          break;
        }
      }
#ifdef RARDLL
      bool DllVolChanged=false;

      if (Cmd->Callback!=NULL)
      {
        GetWideName(NextName,NextNameW,NextNameW,ASIZE(NextNameW));
        char CurName[ASIZE(NextName)];
        strcpy(CurName,NextName);
        wchar CurNameW[ASIZE(NextNameW)];
        wcscpy(CurNameW,NextNameW);
        if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextNameW,RAR_VOL_ASK)!=-1 &&
            wcscmp(CurNameW,NextNameW)!=0)
        {
          *NextName=0;
          DllVolChanged=true;
        }
        else
          if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)!=-1 &&
              strcmp(CurName,NextName)!=0)
          {
            *NextNameW=0;
            DllVolChanged=true;
          }
      }
      if (!DllVolChanged && Cmd->ChangeVolProc!=NULL)
      {
        // Here we preserve ESP value. It is necessary for those developers,
        // who still define ChangeVolProc callback as "C" type function,
        // even though in year 2001 we announced in unrar.dll whatsnew.txt
        // that it will be PASCAL type (for compatibility with Visual Basic).
#if defined(_MSC_VER)
#ifndef _WIN_64
        __asm mov ebx,esp
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
        _EBX=_ESP;
#endif
        int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);

        // Restore ESP after ChangeVolProc with wrongly defined calling
        // convention broken it.
#if defined(_MSC_VER)
#ifndef _WIN_64
      __asm mov esp,ebx
#endif
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
      _ESP=_EBX;
#endif
      if (RetCode!=0)
      {
        *NextNameW=0;
        DllVolChanged=true;
      }
    }
    if (!DllVolChanged)
    {
      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,NextNameW))
#endif
      {
        FailedOpen=true;
        break;
      }

#endif // RARDLL
    }
  
  if (FailedOpen)
  {
#if !defined(SILENT) && !defined(_WIN_CE)
      Log(Arc.FileName,St(MAbsNextVol),NextName);
#endif
    Arc.Open(Arc.FileName,Arc.FileNameW,0);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return(false);
  }
  Arc.CheckArc(true);
#ifdef RARDLL
  if (Cmd->Callback!=NULL)
  {
    GetWideName(NextName,NextNameW,NextNameW,ASIZE(NextNameW));
    if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextNameW,RAR_VOL_NOTIFY)==-1)
      return(false);
    if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
      return(false);
  }
  if (Cmd->ChangeVolProc!=NULL)
  {
#if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
    _EBX=_ESP;
#endif
    int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
#if defined(_WIN_ALL) && !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)!=0;
      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);
}
Beispiel #4
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];
  strcpy(NextName,Arc.FileName);
  NextVolumeName(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))
  {
    if (!OldSchemeTested)
    {
      char AltNextName[NM];
      strcpy(AltNextName,Arc.FileName);
      NextVolumeName(AltNextName,true);
      OldSchemeTested=true;
      if (Arc.Open(AltNextName))
      {
        strcpy(NextName,AltNextName);
        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)
    {
//#ifdef _WIN_32
//      _EBX=_ESP;
//#endif
      int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
//#ifdef _WIN_32
//      _ESP=_EBX;
//#endif
      if (RetCode==0)
      {
        Cmd->DllError=ERAR_EOPEN;
        FailedOpen=true;
        break;
      }
    }
#else

#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))
    {
      Log(Arc.FileName,St(MAbsNextVol),NextName);
      FailedOpen=true;
      break;
    }
#endif
#ifndef SILENT
    if (Cmd->AllYes || !AskNextVol(NextName))
#endif
    {
      FailedOpen=true;
      break;
    }
#endif
  }
  if (FailedOpen)
  {
    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)
  {
//#ifdef _WIN_32
//    _EBX=_ESP;
//#endif
    int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
//#ifdef _WIN_32
//    _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)
  {
    mprintf(St(MExtrPoints),IntNameToExt(Arc.NewLhd.FileName));
    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);
}
Beispiel #5
0
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Command)
{
  RAROptions *Cmd=Arc.GetRAROptions();

  HEADER_TYPE HeaderType=Arc.GetHeaderType();
  FileHeader *hd=HeaderType==HEAD_SERVICE ? &Arc.SubHead:&Arc.FileHead;
  bool SplitHeader=(HeaderType==HEAD_FILE || HeaderType==HEAD_SERVICE) &&
                   hd->SplitAfter;

  if (DataIO!=NULL && SplitHeader)
  {
    bool PackedHashPresent=Arc.Format==RARFMT50 || 
         hd->UnpVer>=20 && hd->FileHash.CRC32!=0xffffffff;
    if (PackedHashPresent && 
        !DataIO->PackedDataHash.Cmp(&hd->FileHash,hd->UseHashKey ? hd->HashKey:NULL))
      uiMsg(UIERROR_CHECKSUMPACKED, Arc.FileName, hd->FileName);
  }

  int64 PosBeforeClose=Arc.Tell();

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


  Arc.Close();

  wchar NextName[NM];
  wcscpy(NextName,Arc.FileName);
  NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);

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

#if !defined(GUI) && !defined(SILENT)
  // In -vp mode we force the pause before next volume even if it is present
  // and even if we are on the hard disk. It is important when user does not
  // want to process partially downloaded volumes preliminary.
  if (Cmd->VolumePause && !uiAskNextVolume(NextName,ASIZE(NextName)))
    FailedOpen=true;
#endif

  uint OpenMode = Cmd->OpenShared ? FMF_OPENSHARED : 0;

  if (!FailedOpen)
    while (!Arc.Open(NextName,OpenMode))
    {
      // 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.
        wchar AltNextName[NM];
        wcscpy(AltNextName,Arc.FileName);
        NextVolumeName(AltNextName,ASIZE(AltNextName),true);
        OldSchemeTested=true;
        if (Arc.Open(AltNextName,OpenMode))
        {
          wcscpy(NextName,AltNextName);
          break;
        }
      }
#ifdef RARDLL
      if (!DllVolChange(Cmd,NextName,ASIZE(NextName)))
      {
        FailedOpen=true;
        break;
      }
#else // !RARDLL

#ifndef SFX_MODULE
      if (!RecoveryDone)
      {
        RecVolumesRestore(Cmd,Arc.FileName,true);
        RecoveryDone=true;
        continue;
      }
#endif

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

#endif // RARDLL
    }
  
  if (FailedOpen)
  {
    uiMsg(UIERROR_MISSINGVOL,NextName);
    Arc.Open(Arc.FileName,OpenMode);
    Arc.Seek(PosBeforeClose,SEEK_SET);
    return false;
  }

  if (Command=='T' || Command=='X' || Command=='E')
    mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);


  Arc.CheckArc(true);
#ifdef RARDLL
  if (!DllVolNotify(Cmd,NextName))
    return false;
#endif

  if (SplitHeader)
    Arc.SearchBlock(HeaderType);
  else
    Arc.ReadHeader();
  if (Arc.GetHeaderType()==HEAD_FILE)
  {
    Arc.ConvertAttributes();
    Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);
  }
#ifndef GUI
  if (ShowFileName)
  {
    mprintf(St(MExtrPoints),Arc.FileHead.FileName);
    if (!Cmd->DisablePercentage)
      mprintf(L"     ");
  }
#endif
  if (DataIO!=NULL)
  {
    if (HeaderType==HEAD_ENDARC)
      DataIO->UnpVolume=false;
    else
    {
      DataIO->UnpVolume=hd->SplitAfter;
      DataIO->SetPackedSizeToRead(hd->PackSize);
    }
#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->PackedDataHash.Init(hd->FileHash.Type,Cmd->Threads);
  }
  return true;
}
Beispiel #6
0
/*-------------------------------------------------------------------------*\
  List the files in a RAR file
  rarfile    - Name of the RAR file to uncompress
  list      - Output. A list of file data of the files in the archive.
                The list should be freed with urarlib_freelist().
  libpassword - Password (for encrypted archives)
\*-------------------------------------------------------------------------*/
int urarlib_list(char *rarfile, ArchiveList_struct **ppList, char *libpassword, bool stopattwo)
{
  if (!ppList)
    return 0;
  uint FileCount = 0;
  InitCRC();

  // Set the arguments for the extract command
  auto_ptr<CommandData> pCmd( new CommandData );

  {
    strcpy(pCmd->Command, "L");
    pCmd->AddArcName(rarfile, NULL);
    pCmd->FileArgs->AddString(MASKALL);
    pCmd->ParseArg((char*)"-va",NULL);

    // Set password for encrypted archives
    if (libpassword)
    {
      strncpy(pCmd->Password, libpassword, sizeof(pCmd->Password) - 1);
      pCmd->Password[sizeof(pCmd->Password) - 1] = '\0';
    }

    // Opent the archive
    auto_ptr<Archive> pArc( new Archive(pCmd.get()) );
    if ( pArc.get() )
    {
      if (!pArc->WOpen(rarfile,NULL))
        return 0;

      FileCount=0;
      *ppList = NULL;
      ArchiveList_struct *pPrev = NULL;
      int iArchive=0;
      while (1)
      {
        if (pArc->IsOpened() && pArc->IsArchive(true))
        {
          int64_t iOffset = pArc->NextBlockPos;
          while(pArc->ReadHeader()>0)
          {
            if (pArc->GetHeaderType() == FILE_HEAD)
            {
              if (pPrev)
                if (strcasecmp(pArc->NewLhd.FileName,pPrev->item.Name)==0)
                {
                  iOffset = pArc->NextBlockPos;
                  pArc->SeekToNext();
                  continue;
                }

              IntToExt(pArc->NewLhd.FileName,pArc->NewLhd.FileName);
              ArchiveList_struct *pCurr = (ArchiveList_struct *)malloc(sizeof(ArchiveList_struct));
              if (!pCurr)
                break;
              if (pPrev)
                pPrev->next = pCurr;
              if (!*ppList)
                *ppList = pCurr;
              pCurr->item.NameSize = strlen(pArc->NewLhd.FileName);
              // sanity check - if it fails the archive is likely corrupt
              if (pCurr->item.NameSize > NM)
              {
                File::RemoveCreated();
                return 0;
              }

              pCurr->item.Name = (char *)malloc(pCurr->item.NameSize + 1);
              strcpy(pCurr->item.Name, pArc->NewLhd.FileName);
              pCurr->item.NameW = (wchar *)malloc((pCurr->item.NameSize + 1)*sizeof(wchar));
              wcscpy(pCurr->item.NameW, pArc->NewLhd.FileNameW);
              pCurr->item.PackSize = pArc->NewLhd.PackSize;
              pCurr->item.UnpSize = int32to64(pArc->NewLhd.HighUnpSize,pArc->NewLhd.UnpSize);
              pCurr->item.HostOS = pArc->NewLhd.HostOS;
              pCurr->item.FileCRC = pArc->NewLhd.FileCRC;
              pCurr->item.FileTime = pArc->NewLhd.FileTime;
              pCurr->item.UnpVer = pArc->NewLhd.UnpVer;
              pCurr->item.Method = pArc->NewLhd.Method;
              pCurr->item.FileAttr = pArc->NewLhd.FileAttr;
              pCurr->item.iOffset = iOffset;
              pCurr->next = NULL;
              pPrev = pCurr;
              FileCount++;
              if (stopattwo && FileCount > 1)
                break;
            }
            iOffset = pArc->NextBlockPos;
            if (iOffset > pArc->FileLength())
            {
              File::RemoveCreated();
              return 0;
            }
            pArc->SeekToNext();
          }
          if (pCmd->VolSize!=0 && ((pArc->NewLhd.Flags & LHD_SPLIT_AFTER) || (pArc->GetHeaderType()==ENDARC_HEAD && (pArc->EndArcHead.Flags & EARC_NEXT_VOLUME)!=0)))
          {
            if (FileCount == 1 && iArchive==0)
            {
              char NextName[NM];
              char LastName[NM];
              strcpy(NextName,pArc->FileName);
              while (XBMC->FileExists(NextName, true))
              {
                strcpy(LastName,NextName);
                NextVolumeName(NextName,(pArc->NewMhd.Flags & MHD_NEWNUMBERING)==0 || pArc->OldFormat);
              }
               Archive arc;
              if (arc.WOpen(LastName,NULL))
              {
                bool bBreak=false;
                while(arc.ReadHeader()>0)
                {
                  if (arc.GetHeaderType() == FILE_HEAD)
                    if (strcasecmp(arc.NewLhd.FileName,pPrev->item.Name)==0)
                    {
                      bBreak=true;
                      break;  
                    }
//                  iOffset = pArc->Tell();
                  arc.SeekToNext();
                }
                if (bBreak)
                {
                  break;
                }
              }
            }
            if (MergeArchive(*pArc,NULL,false,*pCmd->Command))
            {
              iArchive++;
              pArc->Seek(0,SEEK_SET); 
            }
            else
              break;
          }
          else
            break;
        }
        else
          break;
      }
    }
  }

  File::RemoveCreated();
  return FileCount;
}
Beispiel #7
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);
}