Beispiel #1
0
SRes SzArEx_Extract( const CSzArEx *p, ISeekInStream *inStream, const UInt16 *outputDir, ICompressProgress *progress, ISzAlloc *allocTemp)
{
	UInt32 blockIndex = 0xffffffff;
	UInt64 totalUnpackSize = 0;
	UInt32 i;
	SRes res = SZ_OK;

	for (i = 0; i < p->db.NumFolders; i++)
	{
		CSzFolder *folder = p->db.Folders + i;
		UInt64 unpackSize = SzFolder_GetUnpackSize(folder);
		totalUnpackSize += unpackSize;
	}

	if(progress != NULL)
		CompressCallback_Init((CCompressCallback*)progress,totalUnpackSize);

	for (i = 0; i < p->db.NumFiles; i++)
	{
		UInt32 folderIndex = p->FileIndexToFolderIndexMap[i];
		if (folderIndex == (UInt32)-1)
		{
			blockIndex = folderIndex;
			continue;
		}

		if(folderIndex != blockIndex)
		{
			CSzFolder *folder = p->db.Folders + folderIndex;
			UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
			size_t unpackSize = (size_t)unpackSizeSpec;
			UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

			CFolderOutStream outStream;
			FolderOutStream_Init(&outStream,p,folderIndex,outputDir);

			if (unpackSize != unpackSizeSpec)
				return SZ_ERROR_MEM;

			blockIndex = folderIndex;

			res = SzFolder_Decode(folder,
				p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
				inStream, startOffset,
				&outStream.s, unpackSize, progress, allocTemp);

			File_Close(&outStream.file);

			if(res != SZ_OK)
				break;
		}
	}

	return res;
}
Beispiel #2
0
void FolderOutStream_Init(CFolderOutStream *p, const CSzArEx* ar, UInt32 folderIndex, const UInt16* outputDir)
{
	p->s.Write = FolderOutStream_Write;
	p->ar = ar;
	p->startIndex = ar->FolderStartFileIndex[folderIndex];
	p->currentIndex = 0;
	p->folderSize = SzFolder_GetUnpackSize(ar->db.Folders + folderIndex);
	p->fileSize = 0;
	p->crc = CRC_INIT_VAL;
	p->checkCrc = False;
	p->outputDir = outputDir;
	p->bufPos = 0;
	File_Construct(&p->file);
}
Beispiel #3
0
static SRes SzReadAndDecodePackedStreams2(
    ISeekInStream *inStream,
    CSzData *sd,
    ISeqOutStream *outStream,
    UInt64 baseOffset,
    CSzAr *p,
    UInt64 **unpackSizes,
    Byte **digestsDefined,
    UInt32 **digests,
    ISzAlloc *allocTemp)
{
  CMemOutStream* memStream;
  UInt32 numUnpackStreams = 0;
  UInt64 dataStartPos;
  CSzFolder *folder;
  UInt64 unpackSize;
  SRes res;
  Int64 offset;

  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
      allocTemp, allocTemp));
  
  dataStartPos += baseOffset;
  if (p->NumFolders != 1)
    return SZ_ERROR_ARCHIVE;

  folder = p->Folders;
  unpackSize = SzFolder_GetUnpackSize(folder);
  
  offset = (Int64)dataStartPos;
  RINOK(inStream->Seek(inStream, &offset, SZ_SEEK_SET));

  memStream = (CMemOutStream*)outStream;
  if (!Buf_Create((CBuf*)&memStream->data, (size_t)unpackSize, allocTemp))
    return SZ_ERROR_MEM;
  
  res = SzFolder_Decode(folder, p->PackSizes,
          inStream, dataStartPos,
          outStream, (size_t)unpackSize, NULL, allocTemp);
  RINOK(res);
  if (folder->UnpackCRCDefined)
    if (CrcCalc(memStream->data, (size_t)unpackSize) != folder->UnpackCRC)
      return SZ_ERROR_CRC;
  return SZ_OK;
}
Beispiel #4
0
static SRes SzReadAndDecodePackedStreams2(
    ILookInStream *inStream,
    CSzData *sd,
    CBuf *outBuffer,
    UInt64 baseOffset,
    CSzAr *p,
    UInt64 **unpackSizes,
    Byte **digestsDefined,
    UInt32 **digests,
    ISzAlloc *allocTemp)
{

  UInt32 numUnpackStreams = 0;
  UInt64 dataStartPos;
  CSzFolder *folder;
  UInt64 unpackSize;
  SRes res;

  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
      allocTemp, allocTemp));
  
  dataStartPos += baseOffset;
  if (p->NumFolders != 1)
    return SZ_ERROR_ARCHIVE;

  folder = p->Folders;
  unpackSize = SzFolder_GetUnpackSize(folder);
  
  RINOK(LookInStream_SeekTo(inStream, dataStartPos));

  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
    return SZ_ERROR_MEM;
  
  res = SzFolder_Decode(folder, p->PackSizes,
          inStream, dataStartPos,
          outBuffer->data, (size_t)unpackSize, allocTemp);
  RINOK(res);
#ifdef _7ZIP_CRC_SUPPORT
  if (folder->UnpackCRCDefined)
    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
      return SZ_ERROR_CRC;
#endif
  return SZ_OK;
}
Beispiel #5
0
static SRes SzReadSubStreamsInfo(
      CSzData *sd,
      uint32_t numFolders,
      CSzFolder *folders,
      uint32_t *numUnpackStreams,
      uint64_t **unpackSizes,
      uint8_t **digestsDefined,
      uint32_t **digests,
      ISzAlloc *allocTemp)
{
   uint64_t type = 0;
   uint32_t i;
   uint32_t si = 0;
   uint32_t numDigests = 0;

   for (i = 0; i < numFolders; i++)
      folders[i].NumUnpackStreams = 1;
   *numUnpackStreams = numFolders;

   for (;;)
   {
      RINOK(SzReadID(sd, &type));
      if (type == k7zIdNumUnpackStream)
      {
         *numUnpackStreams = 0;
         for (i = 0; i < numFolders; i++)
         {
            uint32_t numStreams;
            RINOK(SzReadNumber32(sd, &numStreams));
            folders[i].NumUnpackStreams = numStreams;
            *numUnpackStreams += numStreams;
         }
         continue;
      }
      if (type == k7zIdCRC || type == k7zIdSize)
         break;
      if (type == k7zIdEnd)
         break;
      RINOK(SzSkeepData(sd));
   }

   if (*numUnpackStreams == 0)
   {
      *unpackSizes = 0;
      *digestsDefined = 0;
      *digests = 0;
   }
   else
   {
      *unpackSizes = (uint64_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint64_t));
      RINOM(*unpackSizes);
      *digestsDefined = (uint8_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint8_t));
      RINOM(*digestsDefined);
      *digests = (uint32_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint32_t));
      RINOM(*digests);
   }

   for (i = 0; i < numFolders; i++)
   {
      /*
         v3.13 incorrectly worked with empty folders
         v4.07: we check that folder is empty
         */
      uint64_t sum = 0;
      uint32_t j;
      uint32_t numSubstreams = folders[i].NumUnpackStreams;
      if (numSubstreams == 0)
         continue;
      if (type == k7zIdSize)
         for (j = 1; j < numSubstreams; j++)
         {
            uint64_t size;
            RINOK(SzReadNumber(sd, &size));
            (*unpackSizes)[si++] = size;
            sum += size;
         }
      (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;
   }
   if (type == k7zIdSize)
   {
      RINOK(SzReadID(sd, &type));
   }

   for (i = 0; i < *numUnpackStreams; i++)
   {
      (*digestsDefined)[i] = 0;
      (*digests)[i] = 0;
   }


   for (i = 0; i < numFolders; i++)
   {
      uint32_t numSubstreams = folders[i].NumUnpackStreams;
      if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
         numDigests += numSubstreams;
   }


   si = 0;
   for (;;)
   {
      if (type == k7zIdCRC)
      {
         int digestIndex = 0;
         uint8_t *digestsDefined2 = 0;
         uint32_t *digests2 = 0;
         SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);
         if (res == SZ_OK)
         {
            for (i = 0; i < numFolders; i++)
            {
               CSzFolder *folder = folders + i;
               uint32_t numSubstreams = folder->NumUnpackStreams;
               if (numSubstreams == 1 && folder->UnpackCRCDefined)
               {
                  (*digestsDefined)[si] = 1;
                  (*digests)[si] = folder->UnpackCRC;
                  si++;
               }
               else
               {
                  uint32_t j;
                  for (j = 0; j < numSubstreams; j++, digestIndex++)
                  {
                     (*digestsDefined)[si] = digestsDefined2[digestIndex];
                     (*digests)[si] = digests2[digestIndex];
                     si++;
                  }
               }
            }
         }
         IAlloc_Free(allocTemp, digestsDefined2);
         IAlloc_Free(allocTemp, digests2);
         RINOK(res);
      }
      else if (type == k7zIdEnd)
         return SZ_OK;
      else
      {
         RINOK(SzSkeepData(sd));
      }
      RINOK(SzReadID(sd, &type));
   }
}
Beispiel #6
0
SRes SzArEx_Extract(
      const CSzArEx *p,
      ILookInStream *inStream,
      uint32_t fileIndex,
      uint32_t *blockIndex,
      uint8_t **outBuffer,
      size_t *outBufferSize,
      size_t *offset,
      size_t *outSizeProcessed,
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint32_t folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
   SRes res = SZ_OK;
   *offset = 0;
   *outSizeProcessed = 0;
   if (folderIndex == (uint32_t)-1)
   {
      IAlloc_Free(allocMain, *outBuffer);
      *blockIndex = folderIndex;
      *outBuffer = 0;
      *outBufferSize = 0;
      return SZ_OK;
   }

   if (*outBuffer == 0 || *blockIndex != folderIndex)
   {
      CSzFolder *folder = p->db.Folders + folderIndex;
      uint64_t unpackSizeSpec = SzFolder_GetUnpackSize(folder);
      size_t unpackSize = (size_t)unpackSizeSpec;
      uint64_t startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

      if (unpackSize != unpackSizeSpec)
         return SZ_ERROR_MEM;
      *blockIndex = folderIndex;
      IAlloc_Free(allocMain, *outBuffer);
      *outBuffer = 0;

      RINOK(LookInStream_SeekTo(inStream, startOffset));

      if (res == SZ_OK)
      {
         *outBufferSize = unpackSize;
         if (unpackSize != 0)
         {
            *outBuffer = (uint8_t *)IAlloc_Alloc(allocMain, unpackSize);
            if (*outBuffer == 0)
               res = SZ_ERROR_MEM;
         }
         if (res == SZ_OK)
         {
            res = SzFolder_Decode(folder,
                  p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
                  inStream, startOffset,
                  *outBuffer, unpackSize, allocTemp);
            if (res == SZ_OK)
            {
               if (folder->UnpackCRCDefined)
               {
                  if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
                     res = SZ_ERROR_CRC;
               }
            }
         }
      }
   }
   if (res == SZ_OK)
   {
      uint32_t i;
      CSzFileItem *fileItem = p->db.Files + fileIndex;
      *offset = 0;
      for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
         *offset += (uint32_t)p->db.Files[i].Size;
      *outSizeProcessed = (size_t)fileItem->Size;
      if (*offset + *outSizeProcessed > *outBufferSize)
         return SZ_ERROR_FAIL;
      if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
         res = SZ_ERROR_CRC;
   }
   return res;
}
Beispiel #7
0
CArchive7Zip::CArchive7Zip(const std::string& name) :
	CArchiveBase(name),
	isOpen(false)
{
	blockIndex = 0xFFFFFFFF;
	outBuffer = NULL;
	outBufferSize = 0;

	allocImp.Alloc = SzAlloc;
	allocImp.Free = SzFree;

	allocTempImp.Alloc = SzAllocTemp;
	allocTempImp.Free = SzFreeTemp;

	SzArEx_Init(&db);

	WRes wres = InFile_Open(&archiveStream.file, name.c_str());
	if (wres) {
		boost::system::error_code e(wres, boost::system::get_system_category());
		LogObject() << "Error opening " << name << ": " << e.message() << " (" << e.value() << ")";
		return;
	}

	FileInStream_CreateVTable(&archiveStream);
	LookToRead_CreateVTable(&lookStream, False);

	lookStream.realStream = &archiveStream.s;
	LookToRead_Init(&lookStream);

	CrcGenerateTable();

	SRes res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
	if (res == SZ_OK) {
		isOpen = true;
	} else {
		isOpen = false;
		std::string error;
		switch (res) {
			case SZ_ERROR_FAIL:
				error = "Extracting failed";
				break;
			case SZ_ERROR_CRC:
				error = "CRC error (archive corrupted?)";
				break;
			case SZ_ERROR_INPUT_EOF:
				error = "Unexpected end of file (truncated?)";
				break;
			case SZ_ERROR_MEM:
				error = "Out of memory";
				break;
			case SZ_ERROR_UNSUPPORTED:
				error = "Unsupported archive";
				break;
			case SZ_ERROR_NO_ARCHIVE:
				error = "Archive not found";
				break;
			default:
				error = "Unknown error";
				break;
		}
		LogObject() << "Error opening " << name << ": " << error;
		return;
	}

	// In 7zip talk, folders are pack-units (solid blocks),
	// not related to file-system folders.
	UInt64* folderUnpackSizes = new UInt64[db.db.NumFolders];
	for (int fi = 0; fi < db.db.NumFolders; fi++) {
		folderUnpackSizes[fi] = SzFolder_GetUnpackSize(db.db.Folders + fi);
	}

	// Get contents of archive and store name->int mapping
	for (unsigned i = 0; i < db.db.NumFiles; ++i) {
		CSzFileItem* f = db.db.Files + i;
		if ((f->Size >= 0) && !f->IsDir) {
			std::string fileName = f->Name;

			FileData fd;
			fd.origName = fileName;
			fd.fp = i;
			fd.size = f->Size;
			fd.crc = (f->Size > 0) ? f->FileCRC : 0;
			const UInt32 folderIndex = db.FileIndexToFolderIndexMap[i];
			if (folderIndex == ((UInt32)-1)) {
				// file has no folder assigned
				fd.unpackedSize = f->Size;
				fd.packedSize   = f->Size;
			} else {
				fd.unpackedSize = folderUnpackSizes[folderIndex];
				fd.packedSize   = db.db.PackSizes[folderIndex];
			}

			StringToLowerInPlace(fileName);
			fileData.push_back(fd);
			lcNameIndex[fileName] = fileData.size()-1;
		}
	}

	delete [] folderUnpackSizes;
}
Beispiel #8
0
SRes SzAr_Extract(
    const CSzArEx *p,
    ISzInStream *inStream,
    UInt32 fileIndex,
    UInt32 *blockIndex,
    Byte **outBuffer,
    size_t *outBufferSize,
    size_t *offset,
    size_t *outSizeProcessed,
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
  SRes res = SZ_OK;
  *offset = 0;
  *outSizeProcessed = 0;
  if (folderIndex == (UInt32)-1)
  {
    IAlloc_Free(allocMain, *outBuffer);
    *blockIndex = folderIndex;
    *outBuffer = 0;
    *outBufferSize = 0;
    return SZ_OK;
  }

  if (*outBuffer == 0 || *blockIndex != folderIndex)
  {
    CSzFolder *folder = p->db.Folders + folderIndex;
    CFileSize unpackSizeSpec = SzFolder_GetUnpackSize(folder);
    size_t unpackSize = (size_t)unpackSizeSpec;
    CFileSize startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

    if (unpackSize != unpackSizeSpec)
      return SZ_ERROR_MEM;
    *blockIndex = folderIndex;
    IAlloc_Free(allocMain, *outBuffer);
    *outBuffer = 0;
    
    RINOK(inStream->Seek(inStream, startOffset, SZ_SEEK_SET));
    
    if (res == SZ_OK)
    {
      *outBufferSize = unpackSize;
      if (unpackSize != 0)
      {
        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
        if (*outBuffer == 0)
          res = SZ_ERROR_MEM;
      }
      if (res == SZ_OK)
      {
        res = SzDecode(p->db.PackSizes +
          p->FolderStartPackStreamIndex[folderIndex], folder,
          inStream, startOffset,
          *outBuffer, unpackSize, allocTemp);
        if (res == SZ_OK)
        {
          if (folder->UnpackCRCDefined)
          {
            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
              res = SZ_ERROR_CRC;
          }
        }
      }
    }
  }
  if (res == SZ_OK)
  {
    UInt32 i;
    CSzFileItem *fileItem = p->db.Files + fileIndex;
    *offset = 0;
    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
      *offset += (UInt32)p->db.Files[i].Size;
    *outSizeProcessed = (size_t)fileItem->Size;
    if (*offset + *outSizeProcessed > *outBufferSize)
      return SZ_ERROR_FAIL;
    {
      if (fileItem->FileCRCDefined)
      {
        if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
          res = SZ_ERROR_CRC;
      }
    }
  }
  return res;
}
Beispiel #9
0
SRes SzArEx_Extract(
    const CSzArEx *p,
    ILookInStream *inStream,
    UInt32 fileIndex,
    SzArEx_DictCache *dictCache,
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
  SRes res = SZ_OK;
  dictCache->entryOffset = 0;
  dictCache->outSizeProcessed = 0;
  if (folderIndex == (UInt32)-1)
  {
    SzArEx_DictCache_free(dictCache);
    dictCache->blockIndex = folderIndex;
    return SZ_OK;
  }

  if (dictCache->outBuffer == 0 || dictCache->blockIndex != folderIndex)
  {
    CSzFolder *folder = p->db.Folders + folderIndex;
    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
    size_t unpackSize = (size_t)unpackSizeSpec;
    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

    if (unpackSize != unpackSizeSpec)
      return SZ_ERROR_MEM;
    
    SzArEx_DictCache_free(dictCache);
    dictCache->blockIndex = folderIndex;

    RINOK(LookInStream_SeekTo(inStream, startOffset));
    
    if (res == SZ_OK)
    {
      dictCache->outBufferSize = unpackSize;
      if (unpackSize != 0)
      {
        if (dictCache->mapFilename && (unpackSize >= k7zUnpackMapDictionaryInMemoryMaxNumBytes)) {
          // map to disk is enabled and file is larger than 1 megabyte.
          // note that an error condition is checked by seeing if
          // dictCache->outBuffer after a map attempt
          SzArEx_DictCache_mmap(dictCache);
        } else {
          dictCache->outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
        }
        if (dictCache->outBuffer == 0)
          res = SZ_ERROR_MEM;
      }
      if (res == SZ_OK)
      {
        res = SzFolder_Decode(folder,
          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
          inStream, startOffset,
          dictCache->outBuffer, unpackSize, allocTemp);
        if (res == SZ_OK)
        {
          if (folder->UnpackCRCDefined)
          {
#ifdef _7ZIP_CRC_SUPPORT
            if (CrcCalc(dictCache->outBuffer, unpackSize) != folder->UnpackCRC)
              res = SZ_ERROR_CRC;
#endif
          }
        }
      }
    }
  }
  if (res == SZ_OK)
  {
    UInt32 i;
    CSzFileItem *fileItem = p->db.Files + fileIndex;
    dictCache->entryOffset = 0;
    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
      dictCache->entryOffset += (UInt32)p->db.Files[i].Size;
    dictCache->outSizeProcessed = (size_t)fileItem->Size;
    if (dictCache->entryOffset + dictCache->outSizeProcessed > dictCache->outBufferSize)
      return SZ_ERROR_FAIL;
#ifdef _7ZIP_CRC_SUPPORT
    if (fileItem->CrcDefined && CrcCalc(dictCache->outBuffer + dictCache->entryOffset, dictCache->outSizeProcessed) != fileItem->Crc)
      res = SZ_ERROR_CRC;
#endif
  }
  return res;
}