Beispiel #1
0
static void *LZMA_openArchive(const char *name, int forWriting)
{
    PHYSFS_uint64 len;
    LZMAarchive *archive = NULL;
    ISzAlloc allocImp;
    ISzAlloc allocTempImp;

    BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
    BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);

    archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
    BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);

    archive->firstEntry = NULL;
    archive->lastEntry = NULL;

    if ((archive->stream.File = __PHYSFS_platformOpenRead(name)) == NULL)
    {
        allocator.Free(archive);
        return NULL;
    } /* if */

    /* Prepare structs for 7z */
    archive->stream.InStream.Read = SzFileReadImp;
    archive->stream.InStream.Seek = SzFileSeekImp;

    allocImp.Alloc = SzAllocPhysicsFS;
    allocImp.Free = SzFreePhysicsFS;

    allocTempImp.Alloc = SzAllocPhysicsFS;
    allocTempImp.Free = SzFreePhysicsFS;

    InitCrcTable();
    SzArDbExInit(&archive->db);
    if (lzma_err(SzArchiveOpen(&archive->stream.InStream, &archive->db,
                               &allocImp, &allocTempImp)) != SZ_OK)
    {
        __PHYSFS_platformClose(archive->stream.File);
        allocator.Free(archive);
        return NULL;
    } /* if */

    len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
    archive->folder = (LZMAfolder *) allocator.Malloc(len);
    BAIL_IF_MACRO(archive->folder == NULL, ERR_OUT_OF_MEMORY, NULL);

    /*
     * Init with 0 so we know when a folder is already cached
     * Values will be set by LZMA_read()
     */
    memset(archive->folder, 0, (size_t) len);

    return(archive);
} /* LZMA_openArchive */
CArchive7Zip::CArchive7Zip(const std::string& name):
	CArchiveBuffered(name),
	curSearchHandle(1),
	isOpen(false)
{
	SZ_RESULT res;

	archiveStream.File = fopen(name.c_str(), "rb");
	if (archiveStream.File == 0)
		return;

	archiveStream.InStream.Read = SzFileReadImp;
	archiveStream.InStream.Seek = SzFileSeekImp;

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

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

	InitCrcTable();
	SzArDbExInit(&db);
	res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
	if (res != SZ_OK)
		return;

	isOpen = true;

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

			FileData fd;
			fd.origName = name;
			fd.fp = i;
			fd.size = fi->Size;
			fd.crc = (fi->Size > 0) ? fi->FileCRC : 0;

			StringToLowerInPlace(name);
			fileData[name] = fd;
		}
	}
}
CArchive7Zip::CArchive7Zip(const string& name) :
    CArchiveBuffered(name),
    isOpen(false),
    curSearchHandle(1)
{
    SZ_RESULT res;

    archiveStream.File = fopen(name.c_str(), "rb");
    if (archiveStream.File == 0)
        return;

    archiveStream.InStream.Read = SzFileReadImp;
    archiveStream.InStream.Seek = SzFileSeekImp;

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

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

    InitCrcTable();
    SzArDbExInit(&db);
    res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
    if (res != SZ_OK)
        return;

    isOpen = true;

    // Get contents of archive and store name->int mapping
    for (int i = 0; i < db.Database.NumFiles; ++i) {
        CFileItem* fi = db.Database.Files + i;
        if (fi->Size > 0) {
            string name = fi->Name;
            //SetSlashesForwardToBack(name);

            FileData fd;
            fd.origName = name;
            fd.fp = i;
            fd.size = fi->Size;

            transform(name.begin(), name.end(), name.begin(), (int (*)(int))tolower);
            fileData[name] = fd;
        }
    }
}
Beispiel #4
0
int main(int numargs, char *args[])
{
  CFileInStream archiveStream;
  CArchiveDatabaseEx db;
  SZ_RESULT res;
  ISzAlloc allocImp;
  ISzAlloc allocTempImp;

  printf("\n7z ANSI-C Decoder 4.43  Copyright (c) 1999-2006 Igor Pavlov  2006-06-04\n");
  if (numargs == 1)
  {
    printf(
      "\nUsage: 7zDec <command> <archive_name>\n\n"
      "<Commands>\n"
      "  e: Extract files from archive\n"
      "  l: List contents of archive\n"
      "  t: Test integrity of archive\n");
    return 0;
  }
  if (numargs < 3)
  {
    PrintError("incorrect command");
    return 1;
  }

  archiveStream.File = fopen(args[2], "rb");
  if (archiveStream.File == 0)
  {
    PrintError("can not open input file");
    return 1;
  }

  archiveStream.InStream.Read = SzFileReadImp;
  archiveStream.InStream.Seek = SzFileSeekImp;

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

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

  InitCrcTable();
  SzArDbExInit(&db);
  res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
  if (res == SZ_OK)
  {
    char *command = args[1];
    int listCommand = 0;
    int testCommand = 0;
    int extractCommand = 0;
    if (strcmp(command, "l") == 0)
      listCommand = 1;
    if (strcmp(command, "t") == 0)
      testCommand = 1;
    else if (strcmp(command, "e") == 0)
      extractCommand = 1;

    if (listCommand)
    {
      UInt32 i;
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        CFileItem *f = db.Database.Files + i;
        printf("%10d  %s\n", (int)f->Size, f->Name);
      }
    }
    else if (testCommand || extractCommand)
    {
      UInt32 i;

      /*
      if you need cache, use these 3 variables.
      if you use external function, you can make these variable as static.
      */
      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

      printf("\n");
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        size_t offset;
        size_t outSizeProcessed;
        CFileItem *f = db.Database.Files + i;
        if (f->IsDirectory)
          printf("Directory ");
        else
          printf(testCommand ? 
            "Testing   ":
            "Extracting");
        printf(" %s", f->Name);
        if (f->IsDirectory)
        {
          printf("\n");
          continue;
        }
        res = SzExtract(&archiveStream.InStream, &db, i, 
            &blockIndex, &outBuffer, &outBufferSize, 
            &offset, &outSizeProcessed, 
            &allocImp, &allocTempImp);
        if (res != SZ_OK)
          break;
        if (!testCommand)
        {
          FILE *outputHandle;
          size_t processedSize;
          char *fileName = f->Name;
          size_t nameLen = strlen(f->Name);
          for (; nameLen > 0; nameLen--)
            if (f->Name[nameLen - 1] == '/')
            {
              fileName = f->Name + nameLen;
              break;
            }
            
          outputHandle = fopen(fileName, "wb+");
          if (outputHandle == 0)
          {
            PrintError("can not open output file");
            res = SZE_FAIL;
            break;
          }
          processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle);
          if (processedSize != outSizeProcessed)
          {
            PrintError("can not write output file");
            res = SZE_FAIL;
            break;
          }
          if (fclose(outputHandle))
          {
            PrintError("can not close output file");
            res = SZE_FAIL;
            break;
          }
        }
        printf("\n");
      }
      allocImp.Free(outBuffer);
    }
    else
    {
      PrintError("incorrect command");
      res = SZE_FAIL;
    }
  }
  SzArDbExFree(&db, allocImp.Free);

  fclose(archiveStream.File);
  if (res == SZ_OK)
  {
    printf("\nEverything is Ok\n");
    return 0;
  }
  if (res == SZE_OUTOFMEMORY)
    PrintError("can not allocate memory");
  else     
    printf("\nERROR #%d\n", res);
  return 1;
}
Beispiel #5
0
int SzParse(char * filepath)
{
	if(!filepath)
		return 0;
	
	int device;
	
	if(!FindDevice(browser.dir, &device) || !GetFileSize(browser.selIndex))
		return 0;

	int nbfiles = 0;

	// save the length/offset of this file
	unsigned int filelen = browserList[browser.selIndex].length;

	// setup archive stream
	SzArchiveStream.offset = 0;
	SzArchiveStream.len = filelen;
	SzArchiveStream.pos = 0;

	// open file
	file = fopen (filepath, "rb");
	if(!file)
		return 0;

	// set szMethod to current chosen load device
	szMethod = device;

	// set handler functions for reading data from SD/USB/SMB/DVD
	SzArchiveStream.InStream.Read = SzFileReadImp;
	SzArchiveStream.InStream.Seek = SzFileSeekImp;

	// set default 7Zip SDK handlers for allocation and freeing memory
	SzAllocImp.Alloc = SzAlloc;
	SzAllocImp.Free = SzFree;
	SzAllocTempImp.Alloc = SzAllocTemp;
	SzAllocTempImp.Free = SzFreeTemp;

	// prepare CRC and 7Zip database structures
	InitCrcTable();
	SzArDbExInit(&SzDb);

	// open the archive
	SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp,
			&SzAllocTempImp);

	if (SzRes != SZ_OK)
	{
		SzDisplayError(SzRes);
		// free memory used by the 7z SDK
		SzClose();
	}
	else // archive opened successfully
	{
		if(SzDb.Database.NumFiles > 0)
		{
			// Parses the 7z into a full file listing

			HaltParseThread(); // halt parsing
			ResetBrowser(); // reset browser

			// add '..' folder in case the user wants exit the 7z
			AddBrowserEntry();

			sprintf(browserList[0].displayname, "Up One Level");
			browserList[0].isdir = 1;
			browserList[0].length = filelen;
			browserList[0].icon = ICON_FOLDER;

			// get contents and parse them into file list structure
			unsigned int SzI, SzJ;
			SzJ = 1;
			for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++)
			{
				SzF = SzDb.Database.Files + SzI;

				// skip directories
				if (SzF->IsDirectory)
					continue;

				if(!AddBrowserEntry())
				{
					ResetBrowser();
					ErrorPrompt("Out of memory: too many files!");
					SzClose();
					SzJ = 0;
					break;
				}

				// parse information about this file to the file list structure
				snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name);
				StripExt(browserList[SzJ].displayname, browserList[SzJ].filename);
				browserList[SzJ].length = SzF->Size; // filesize
				browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags)
				browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number
				SzJ++;
			}
			nbfiles = SzJ;
		}
		else
		{
			SzClose();
		}
	}

	CancelAction();

	// close file
	fclose(file);
	return nbfiles;
}
Beispiel #6
0
int SzExtractContent(void* ctx, char* archive, char* filename, void** pbuf)
{
	SzContext* archiveStream = (SzContext*)ctx;
	FILE* fp = 0;
	SZ_RESULT res;
	if (!archiveStream->archive || strcmp(archive, archiveStream->archive)) {
		fp = fopen(archive, "rb");
		if (!fp) return -1;
	}
	if (archiveStream->File) {
		if (!archive || fp) {
			archiveStream->allocImp.Free(archiveStream->outBuffer);
			SzArDbExFree(&archiveStream->db, archiveStream->allocImp.Free);
			fclose(archiveStream->File);
			archiveStream->File = 0;
			archiveStream->outBuffer = 0; /* it must be 0 before first call for each new archive. */
			archiveStream->outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */
			if (archiveStream->archive) {
				free(archiveStream->archive);
				archiveStream->archive = 0;
			}
		}
	}
	if (!archive) return -1;
	if (!archiveStream->File) {
		archiveStream->File = fp;

		archiveStream->InStream.Read = SzFileReadImp;
		archiveStream->InStream.Seek = SzFileSeekImp;

		archiveStream->allocImp.Alloc = SzAlloc;
		archiveStream->allocImp.Free = SzFree;

		archiveStream->allocTempImp.Alloc = SzAllocTemp;
		archiveStream->allocTempImp.Free = SzFreeTemp;

		InitCrcTable();
		SzArDbExInit(&archiveStream->db);
		res = SzArchiveOpen(&archiveStream->InStream, &archiveStream->db, &archiveStream->allocImp, &archiveStream->allocTempImp);
		if (res != SZ_OK) {
			SzArDbExFree(&archiveStream->db, archiveStream->allocImp.Free);
			fclose(archiveStream->File);
			archiveStream->File = 0;
			return -1;
		}
		archiveStream->archive = _strdup(archive);
	}

	if (filename) {
		UInt32 i;
		/*
		if you need cache, use these 3 variables.
		if you use external function, you can make these variable as static.
		*/
		UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */

		for (i = 0; i < archiveStream->db.Database.NumFiles; i++)
		{
			size_t offset;
			size_t outSizeProcessed;

			CFileItem *f = archiveStream->db.Database.Files + i;
			if (f->IsDirectory) {
				// is directory
				continue;
			}
			if (strcmp(f->Name, filename)) {
				// not matched
				continue;
			}
			res = SzExtract(&archiveStream->InStream, &archiveStream->db, i, 
				&blockIndex, &archiveStream->outBuffer, &archiveStream->outBufferSize, 
				&offset, &outSizeProcessed, 
				&archiveStream->allocImp, &archiveStream->allocTempImp);
			if (res != SZ_OK) return -1;
			if (pbuf) *pbuf = (void*)(archiveStream->outBuffer + offset);
			return (int)outSizeProcessed;
		}
		return -1;
	} else {
		return archiveStream->db.Database.NumFiles;
	}
}
Beispiel #7
0
static void *LZMA_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
{
    PHYSFS_uint8 sig[k7zSignatureSize];
    size_t len = 0;
    LZMAarchive *archive = NULL;

    assert(io != NULL);  /* shouldn't ever happen. */

    BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);

    if (io->read(io, sig, k7zSignatureSize) != k7zSignatureSize)
        return 0;
    BAIL_IF_MACRO(!TestSignatureCandidate(sig), PHYSFS_ERR_UNSUPPORTED, NULL);
    BAIL_IF_MACRO(!io->seek(io, 0), ERRPASS, NULL);

    archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
    BAIL_IF_MACRO(archive == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);

    lzma_archive_init(archive);
    archive->stream.io = io;

    CrcGenerateTable();
    SzArDbExInit(&archive->db);
    if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
                               &archive->db,
                               &archive->stream.allocImp,
                               &archive->stream.allocTempImp)) != SZ_OK)
    {
        SzArDbExFree(&archive->db, SzFreePhysicsFS);
        lzma_archive_exit(archive);
        return NULL; /* Error is set by lzma_err! */
    } /* if */

    len = archive->db.Database.NumFiles * sizeof (LZMAfile);
    archive->files = (LZMAfile *) allocator.Malloc(len);
    if (archive->files == NULL)
    {
        SzArDbExFree(&archive->db, SzFreePhysicsFS);
        lzma_archive_exit(archive);
        BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
    }

    /*
     * Init with 0 so we know when a folder is already cached
     * Values will be set by LZMA_openRead()
     */
    memset(archive->files, 0, len);

    len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
    archive->folders = (LZMAfolder *) allocator.Malloc(len);
    if (archive->folders == NULL)
    {
        SzArDbExFree(&archive->db, SzFreePhysicsFS);
        lzma_archive_exit(archive);
        BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
    }

    /*
     * Init with 0 so we know when a folder is already cached
     * Values will be set by LZMA_read()
     */
    memset(archive->folders, 0, len);

    if(!lzma_files_init(archive))
    {
        SzArDbExFree(&archive->db, SzFreePhysicsFS);
        lzma_archive_exit(archive);
        BAIL_MACRO(PHYSFS_ERR_OTHER_ERROR, NULL);
    }

    return archive;
} /* LZMA_openArchive */
Beispiel #8
0
int unpack(char archive[512])
{
    UInt32 i;
    CFileInStream archive_stream;
    CArchiveDatabaseEx db;
    SZ_RESULT res;
    ISzAlloc alloc_imp;
    ISzAlloc alloc_temp_imp;
    #ifdef DEBUG
    printf("extracting %s...\n", archive);
    #endif
    archive_stream.File = open_file_r(archive);
    if (archive_stream.File == 0)
    {
        print_error("can not open input file");
        return 1;
    }
    archive_stream.InStream.Read = read_file_imp;
    archive_stream.InStream.Seek = seek_file_imp;
    alloc_imp.Alloc = SzAlloc;
    alloc_imp.Free = SzFree;
    alloc_temp_imp.Alloc = SzAllocTemp;
    alloc_temp_imp.Free = SzFreeTemp;
    CrcGenerateTable();

    //SEEK OFFSET
    size_t offset;
    offset = seek_beginning_of_archive(&archive_stream);

    //INIT DB
    SzArDbExInit(&db);

    //SET THE OFFSET
    g_offset = offset;
    seek_file_imp(&archive_stream.InStream, 0); //seek to beginning of file including offset

    res = SzArchiveOpen(&archive_stream.InStream, &db, &alloc_imp, &alloc_temp_imp);
    #ifdef DEBUG
    printf("res = %i\n",res);
    #endif
    if (res == SZ_OK)
    {
        /*
        if you need cache, use these 3 variables.
        if you use external function, you can make these variable as static.
        */
        UInt32 block_index = 0xFFFFFFFF; /* it can have any value before first call (if out_buffer = 0) */
        Byte *out_buffer = 0; /* it must be 0 before first call for each new archive. */
        size_t out_buffer_size = 0;    /* it can have any value before first call (if out_buffer = 0) */

        //~ for (i = db.Database.NumFolders-1; i >0; i--)
        //~ {
            //~ CFileItem *f = db.Database.Folders + i;
            //~ if (!f->IsDirectory){
            //~ } else {
            //~ }
        //~ }

        for (i = db.Database.NumFiles-1; i >0; i--)
        {
            CFileItem *f = db.Database.Files + i;
            if (!f->IsDirectory){
                continue;
            }
            #ifdef DEBUG
            printf("Creating directory %s", f->Name);
            #endif
            if (create_directory(f->Name) != 0)
            {
                print_error("can not create directory");
            }
            #ifdef DEBUG
            printf("\n");
            #endif
        }

        for (i = 0; i < db.Database.NumFiles; i++)
        {
            CFileItem *f = db.Database.Files + i;
            #ifdef DEBUG
            printf("Extracting %s\n %d %s", f->Name, i, f->IsDirectory);
            #endif
            if (f->IsDirectory){
                continue;
            }
            size_t out_size_processed;
            #ifdef DEBUG
            printf("Extracting %s\n", f->Name);
            #endif
            res = SzExtract(&archive_stream.InStream, &db, i,
                    &block_index, &out_buffer, &out_buffer_size,
                    &offset, &out_size_processed,
                    &alloc_imp, &alloc_temp_imp);

            if (res != SZ_OK)
                break;

            MY_FILE_HANDLE output_handle = open_file_w(f->Name);
            if (output_handle == 0)
            {
                print_error("can not open output file");
                res = SZE_FAIL;
                break;
            }

            size_t processed_size;
            processed_size = write_file(output_handle, out_buffer + offset, out_size_processed);
            if (processed_size != out_size_processed)
            {
                print_error("can not write output file");
                res = SZE_FAIL;
                break;
            }
            if (close_file(output_handle))
            {
                print_error("can not close output file");
                res = SZE_FAIL;
                break;
            }
            #ifdef DEBUG
            printf("\n");
            #endif
        }
        alloc_imp.Free(out_buffer);
    }
    SzArDbExFree(&db, alloc_imp.Free);

    close_file(archive_stream.File);
    if (res == SZ_OK)
    {
        #ifdef DEBUG
        printf("\nEverything is Ok\n");
        #endif
        return 0;
    }
    if (res == (SZ_RESULT)SZE_NOTIMPL)
        print_error("decoder doesn't support this archive");
    else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
        print_error("can not allocate memory");
    else if (res == (SZ_RESULT)SZE_CRC_ERROR)
        print_error("CRC error");
    else
        print_error("Unknown error"); //TBD print res
    return 1;
}
Beispiel #9
0
/* Extract all the files from a 7-zip archive to the specified location, with
 * callbacks. "file" is the path to the file to unpack, "base" is the location
 * to extract to, "before_entry_callback" is a function to call right before
 * each entry is unpacked, and "create_callback" is a function to call right
 * after each entry has been unpacked. Both callback functions' arguments are as
 * follows: the path (relative to base) of the entry, and an int that is nonzero
 * if the entry is a directory.
 */
int un7z
 (const char* file,
  const char* base,
  int (*before_entry_callback)(const char*, int),
  void (*create_callback)(const char*, int))
{
	// Create and fill out our reader object
	FileInStream instream;
	instream.sz_stream.Read = SzFileReadImp;
	instream.sz_stream.Seek = SzFileSeekImp;
	instream.filep = fopen(file, "rb");
	if (!instream.filep)
	{
		archive_seterror("failed to open file '%s' for reading", file);
		return -1;
	}
	// Close the FILE* when we leave this scope
	RefType< FILE >::Ref fcloser(instream.filep, fclose);

	CrcGenerateTable();

	CArchiveDatabaseEx db;
	SzArDbExInit(&db);
	// Free up the database when we leave this scope
	RefType< CArchiveDatabaseEx >::Ref db_deleter(&db, SzArDbExDeleter);

	// Set up 7-zip's memory allocation scheme (uses the default allocators)
	ISzAlloc allocImp, allocTempImp;
	allocImp.Alloc = SzAlloc;
	allocImp.Free = SzFree;
	allocTempImp.Alloc = SzAllocTemp;
	allocTempImp.Free = SzFreeTemp;

	// Open the archive
	if (SzArchiveOpen(&instream.sz_stream, &db, &allocImp, &allocTempImp)
	 != SZ_OK)
	{
		archive_seterror("7zlib couldn't open '%s' as a 7z archive", file);
		return -1;
	}

	// Update progress total
	num_files_in_cur_op = db.Database.NumFiles;

	// Set up 7-zip's "cache" variables
	UInt32 blockIndex = 0xFFFFFFFF;
	Byte *outBuffer = 0;
	size_t outBufferSize = 0;
	// Delete the buffer when we leave this scope
	RefType< Byte >::Ref outbuf_deleter(outBuffer, OutBufferDeleter);

	// Iterate and extract entries
	for (unsigned i = 0; i < db.Database.NumFiles; i++)
	{
		// Update progress
		cur_file_in_op_index = i;

		CFileItem* cur_file = &db.Database.Files[i];
		
		// Call before-extraction callback
		if (before_entry_callback)
		{
			int cbres = before_entry_callback(cur_file->Name, cur_file->IsDirectory);
			if (cbres != 0)
			{
				archive_seterror("7zlib failed to unzip '%s': cancelled from "
				 "callback", cur_file->Name);
				return cbres;
			}
		}

		// Get the full path to output
		std::string out_path = std::string(base) + "/" + cur_file->Name;

		// If entry is a directory, merely create the directory
		if (cur_file->IsDirectory)
		{
			if (!makedir(base, cur_file->Name))
			{
				archive_seterror("couldn't create directory '%s'",
				 out_path.c_str());
				return -1;
			}
		}
		// If entry is a file, extract it
		else
		{
			size_t offset, outSizeProcessed;
			// 7-zip seems to encourage getting the whole file in one blow
			SZ_RESULT res = SzExtract(&instream.sz_stream, &db, i, &blockIndex,
			 &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp,
			 &allocTempImp);
			if (res == SZE_CRC_ERROR)
			{
				archive_seterror("bad CRC for file '%s' in '%s'",
				 cur_file->Name, file);
				return -1;
			}
			else if (res != SZ_OK)
			{
				archive_seterror("7zlib failed to unpack file '%s' in '%s'",
				 cur_file->Name, file);
				return -1;
			}

			bool was_created = false;
			// If the output file already exists, make sure we can write over it
			if (chmod(out_path.c_str(), _S_IREAD|_S_IWRITE) != 0)
				was_created = true;

			// Open the output file for writing
			FILE* outfile = fopen(out_path.c_str(), "wb");
			if (!outfile)
			{
				// Couldn't open it -- make sure its parent directory exists
				size_t p = std::string(cur_file->Name).find_last_of("/\\", std::string::npos);
				if (p != std::string::npos)
				{
					makedir(base, std::string(cur_file->Name).substr(0, p).c_str());
					outfile = fopen(out_path.c_str(), "wb");
				}
			}
			if (!outfile)
			{
				// Still couldn't open it; error out
				archive_seterror("couldn't open '%s' for writing",
				 out_path.c_str());
				return -1;
			}

			// Write out the whole file and then close it
			int written = fwrite(outBuffer + offset, 1, outSizeProcessed,
			 outfile);
			fclose(outfile);
			if (written <= 0
			 || static_cast< size_t >(written) != outSizeProcessed)
			{
				// At this point we have an empty output file; remove it
				remove(out_path.c_str());
				archive_seterror("failed to write %d bytes to '%s'",
				 outSizeProcessed, out_path.c_str());
				return -1;
			}
		}

		// Set stored attributes
		if (cur_file->AreAttributesDefined)
			SetFileAttributes(out_path.c_str(), cur_file->Attributes);

		// Call after-creation callback
		create_callback(cur_file->Name, cur_file->IsDirectory ? 1 : 0);
	}

	return 0;
}
Beispiel #10
0
int SzParse(char * filepath, int method)
{
	int nbfiles = 0;

	// save the offset and the length of this file inside the archive stream structure
	SzArchiveStream.offset = filelist[selection].offset;
	SzArchiveStream.len = filelist[selection].length;
	SzArchiveStream.pos = 0;

	// open file
	switch (method)
	{
		case METHOD_SD:
		case METHOD_USB:
			fatfile = fopen (filepath, "rb");
			if(!fatfile)
				return 0;
			break;
		case METHOD_SMB:
			smbfile = OpenSMBFile(filepath);
			if(!smbfile)
				return 0;
			break;
	}

	// set szMethod to current chosen load method
	szMethod = method;

	// set handler functions for reading data from FAT/SMB/DVD
	SzArchiveStream.InStream.Read = SzFileReadImp;
	SzArchiveStream.InStream.Seek = SzFileSeekImp;

	// set default 7Zip SDK handlers for allocation and freeing memory
	SzAllocImp.Alloc = SzAlloc;
	SzAllocImp.Free = SzFree;
	SzAllocTempImp.Alloc = SzAllocTemp;
	SzAllocTempImp.Free = SzFreeTemp;

	// prepare CRC and 7Zip database structures
	InitCrcTable();
	SzArDbExInit(&SzDb);

	// open the archive
	SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp,
			&SzAllocTempImp);

	if (SzRes != SZ_OK)
	{
		SzDisplayError(SzRes);
		// free memory used by the 7z SDK
		SzClose();
	}
	else // archive opened successfully
	{
		if(SzDb.Database.NumFiles > 0)
		{
			// Parses the 7z into a full file listing

			// erase all previous entries
			memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES);

			// add '..' folder in case the user wants exit the 7z
			strncpy(filelist[0].displayname, "..", 2);
			filelist[0].flags = 1;
			filelist[0].offset = dvddir;
			filelist[0].length = dvddirlength;

			// get contents and parse them into file list structure
			unsigned int SzI, SzJ;
			SzJ = 1;
			for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++)
			{
				SzF = SzDb.Database.Files + SzI;

				// skip directories
				if (SzF->IsDirectory)
					continue;

				// do not exceed MAXFILES to avoid possible buffer overflows
				if (SzJ == (MAXFILES - 1))
					break;

				// parse information about this file to the dvd file list structure
				strncpy(filelist[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
				filelist[SzJ].filename[MAXJOLIET] = 0; // terminate string
				strncpy(filelist[SzJ].displayname, SzF->Name, MAXDISPLAY+1);	// crop name for display
				filelist[SzJ].length = SzF->Size; // filesize
				filelist[SzJ].offset = SzI; // the extraction function identifies the file with this number
				filelist[SzJ].flags = 0; // only files will be displayed (-> no flags)
				SzJ++;
			}

			// update maxfiles and select the first entry
			offset = selection = 0;
			nbfiles = SzJ;
		}
		else
		{
			SzArDbExFree(&SzDb, SzAllocImp.Free);
		}
	}

	// close file
	switch (method)
	{
		case METHOD_SD:
		case METHOD_USB:
			fclose(fatfile);
			break;
		case METHOD_SMB:
			SMB_CloseFile (smbfile);
			break;
	}
	return nbfiles;
}
Beispiel #11
0
int _7zArchive( STRPTR filename, int mode )
{
  CFileInStream archiveStream;
  CArchiveDatabaseEx db;
  SZ_RESULT res;
  ISzAlloc allocImp;
  ISzAlloc allocTempImp;
  
  archiveStream.File = Open( filename, MODE_OLDFILE);
  if (!archiveStream.File)
  {
    PrintError("Unable to open archive!");
    goto done;
  }

  archiveStream.InStream.zRead = SzFileReadImp;
  archiveStream.InStream.zSeek = SzFileSeekImp;

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

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

  InitCrcTable();
  SzArDbExInit(&db);
  res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
  if (res == SZ_OK)
  {
    if( G->CliUsage )
    {
      ShowProgramInfo ( );
      Printf("\n%s archive %s\n",
        (long)((mode == 1) ? "Listing":((mode == 2) ? "Testing":"Extracting")),
        (long) FilePart( filename ));
    }
    
    if ( mode == 1 ) // LIST mode
    {
      UInt32 i;
      
      if( G->CliUsage )
      {
        Printf("\n%7s%9s%14s%7s%8s\n",(long)"Date",(long)"Time",(long)"Size",(long)"CRC",(long)"Name");
        for( i = 0; i < 60 ; i++ )
          PutStr("-");
        PutStr("\n");
      }
      
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        CFileItem *f = db.Database.Files + i;
        
        if( G->CliUsage )
        {
          UBYTE date[20];
          
          ItemTime( f, date, sizeof(date), FALSE );
          
          Printf("%s%11ld  %08lx  %s\n", (long)date, (long)f->Size,
          	f->IsFileCRCDefined ? f->FileCRC:0, (long)f->Name);
        }
        else
          NListInsert((APTR) f );
      }
    }
    else
    {
      UInt32 i;

      // if you need cache, use these 3 variables.
      // if you use external function, you can make these variable as static.
      UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0) 
      Byte *outBuffer = 0; // it must be 0 before first call for each new archive. 
      size_t outBufferSize = 0;  // it can have any value before first call (if outBuffer = 0) 
      
      if( G->CliUsage )
        PutStr("\n");
      
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        size_t offset;
        size_t outSizeProcessed;
        CFileItem *f = db.Database.Files + i;
        
        if( G->CliUsage )
        {
          #if 0
          if (f->IsDirectory)
            PutStr("Directory");
          else
            Printf("%12s",(long)((mode == 2) ? "Testing":"Extracting"));
          Printf(" %s", (long)f->Name);
          #else
          if (!f->IsDirectory)
            Printf("%12s %s",(long)((mode == 2) ? "Testing":"Extracting"), (long)f->Name);
          #endif
        }
        else
        {
          STATIC UBYTE msg[256];
          
          SNPrintf( msg, sizeof(msg)-1, "%12s %s",
            (mode == 2) ? "Testing":"Extracting", f->Name );
          
          GaugeUpdate( msg, i*100/db.Database.NumFiles );
        }
        if (f->IsDirectory)
        {
        //  if( G->CliUsage )
        //    PutStr("\n");
          continue;
        }
        res = SzExtract(&archiveStream.InStream, &db, i, 
            &blockIndex, &outBuffer, &outBufferSize, 
            &offset, &outSizeProcessed, 
            &allocImp, &allocTempImp);
        if (res != SZ_OK)
          break;
        if ( mode == 3 ) // EXTRACT mode
        {
          BPTR outputHandle;
          UInt32 processedSize;
          
          MakeDir( f->Name ); // creates ALL Directories pointing to this file
          
          outputHandle = Open( f->Name, MODE_NEWFILE );
          if (outputHandle == 0)
          {
            PrintError("Unable to open output file!");
            res = SZE_FAIL;
            break;
          }
          processedSize = Write(outputHandle, outBuffer + offset, outSizeProcessed);
          if (processedSize != outSizeProcessed)
          {
            PrintError("Cannot write to output file!");
            res = SZE_FAIL;
            break;
          }
          Close(outputHandle);
          SetFileTimeToFile( f );
        }
        if( G->CliUsage )
          PutStr("\n");
      }
      allocImp.Free(outBuffer);
    }
  }
  SzArDbExFree(&db, allocImp.Free);

  Close(archiveStream.File);
  if (res == SZ_OK)
  {
    if( G->CliUsage )
      Printf("\n%s\n", (long)"Everything is Ok");
    else
      GaugeUpdate("Everything is Ok", 0 );
    return 0;
  }
#if 0
  if (res == SZE_OUTOFMEMORY)
    PrintError("can not allocate memory");
  else if( G->CliUsage )
    Printf("\nERROR #%ld\n", res);
#else
  PrintError(SzErrorString( res ));
#endif
  if( ! G->CliUsage )
    GaugeUpdate("error %ld procesing archive", res );
    
done:
  return 1;
}
Beispiel #12
0
int SzParse(char * filepath, int method)
{
	if(!filepath)
		return 0;

	int nbfiles = 0;

	// save the length/offset of this file
	unsigned int filelen = browserList[browser.selIndex].length;
	u64 fileoff = browserList[browser.selIndex].offset;

	// setup archive stream
	SzArchiveStream.offset = 0;
	SzArchiveStream.len = filelen;
	SzArchiveStream.pos = 0;

	// open file
	switch (method)
	{
		case METHOD_SD:
		case METHOD_USB:
		case METHOD_SMB:
			file = fopen (filepath, "rb");
			if(!file)
				return 0;
			break;
		case METHOD_DVD:
			SwitchDVDFolder(filepath);
			break;
	}

	// set szMethod to current chosen load method
	szMethod = method;

	// set handler functions for reading data from SD/USB/SMB/DVD
	SzArchiveStream.InStream.Read = SzFileReadImp;
	SzArchiveStream.InStream.Seek = SzFileSeekImp;

	// set default 7Zip SDK handlers for allocation and freeing memory
	SzAllocImp.Alloc = SzAlloc;
	SzAllocImp.Free = SzFree;
	SzAllocTempImp.Alloc = SzAllocTemp;
	SzAllocTempImp.Free = SzFreeTemp;

	// prepare CRC and 7Zip database structures
	InitCrcTable();
	SzArDbExInit(&SzDb);

	// open the archive
	SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp,
			&SzAllocTempImp);

	if (SzRes != SZ_OK)
	{
		SzDisplayError(SzRes);
		// free memory used by the 7z SDK
		SzClose();
	}
	else // archive opened successfully
	{
		if(SzDb.Database.NumFiles > 0)
		{
			// Parses the 7z into a full file listing

			// reset browser
			ResetBrowser();

			// add '..' folder in case the user wants exit the 7z
			strncpy(browserList[0].displayname, "..", 2);
			browserList[0].isdir = 1;
			browserList[0].offset = fileoff;
			browserList[0].length = filelen;

			// get contents and parse them into file list structure
			unsigned int SzI, SzJ;
			SzJ = 1;
			for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++)
			{
				SzF = SzDb.Database.Files + SzI;

				// skip directories
				if (SzF->IsDirectory)
					continue;

				BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (SzJ+1) * sizeof(BROWSERENTRY));

				if(!newBrowserList) // failed to allocate required memory
				{
					ResetBrowser();
					WaitPrompt("Out of memory: too many files!");
					nbfiles = 0;
					break;
				}
				else
				{
					browserList = newBrowserList;
				}
				memset(&(browserList[SzJ]), 0, sizeof(BROWSERENTRY)); // clear the new entry

				// parse information about this file to the dvd file list structure
				strncpy(browserList[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
				strncpy(browserList[SzJ].displayname, SzF->Name, MAXDISPLAY);	// crop name for display
				browserList[SzJ].length = SzF->Size; // filesize
				browserList[SzJ].offset = SzI; // the extraction function identifies the file with this number
				browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags)
				SzJ++;
			}

			nbfiles = SzJ;
		}
		else
		{
			SzArDbExFree(&SzDb, SzAllocImp.Free);
		}
	}

	// close file
	switch (method)
	{
		case METHOD_SD:
		case METHOD_USB:
		case METHOD_SMB:
			fclose(file);
			break;
	}
	return nbfiles;
}
Beispiel #13
0
int main(int numargs, char *args[])
{
  CFileInStream archiveStream;
  CArchiveDatabaseEx db;
  SZ_RESULT res;
  ISzAlloc allocImp;
  ISzAlloc allocTempImp;

  printf("\n7z ANSI-C Decoder 4.48  Copyright (c) 1999-2007 Igor Pavlov  2007-06-21\n");
  if (numargs == 1)
  {
    printf(
      "\nUsage: 7zDec <command> <archive_name>\n\n"
      "<Commands>\n"
      "  e: Extract files from archive\n"
      "  l: List contents of archive\n"
      "  t: Test integrity of archive\n");
    return 0;
  }
  if (numargs < 3)
  {
    PrintError("incorrect command");
    return 1;
  }

  archiveStream.File = 
  #ifdef USE_WINDOWS_FUNCTIONS
  CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ, 
      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (archiveStream.File == INVALID_HANDLE_VALUE)
  #else
  archiveStream.File = fopen(args[2], "rb");
  if (archiveStream.File == 0)
  #endif
  {
    PrintError("can not open input file");
    return 1;
  }

  archiveStream.InStream.Read = SzFileReadImp;
  archiveStream.InStream.Seek = SzFileSeekImp;

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

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

  CrcGenerateTable();

  SzArDbExInit(&db);
  res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
  if (res == SZ_OK)
  {
    char *command = args[1];
    int listCommand = 0;
    int testCommand = 0;
    int extractCommand = 0;
    if (strcmp(command, "l") == 0)
      listCommand = 1;
    if (strcmp(command, "t") == 0)
      testCommand = 1;
    else if (strcmp(command, "e") == 0)
      extractCommand = 1;

    if (listCommand)
    {
      UInt32 i;
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        CFileItem *f = db.Database.Files + i;
        char s[32], t[32];
        ConvertNumberToString(f->Size, s);
        if (f->IsLastWriteTimeDefined)
          ConvertFileTimeToString(&f->LastWriteTime, t);
        else
          strcpy(t, "                   ");

        printf("%10s %s  %s\n", s, t, f->Name);
      }
    }
    else if (testCommand || extractCommand)
    {
      UInt32 i;

      /*
      if you need cache, use these 3 variables.
      if you use external function, you can make these variable as static.
      */
      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

      printf("\n");
      for (i = 0; i < db.Database.NumFiles; i++)
      {
        size_t offset;
        size_t outSizeProcessed;
        CFileItem *f = db.Database.Files + i;
        if (f->IsDirectory)
          printf("Directory ");
        else
          printf(testCommand ? 
            "Testing   ":
            "Extracting");
        printf(" %s", f->Name);
        if (f->IsDirectory)
        {
          printf("\n");
          continue;
        }
        res = SzExtract(&archiveStream.InStream, &db, i, 
            &blockIndex, &outBuffer, &outBufferSize, 
            &offset, &outSizeProcessed, 
            &allocImp, &allocTempImp);
        if (res != SZ_OK)
          break;
        if (!testCommand)
        {
          MY_FILE_HANDLE outputHandle;
          size_t processedSize;
          char *fileName = f->Name;
          size_t nameLen = strlen(f->Name);
          for (; nameLen > 0; nameLen--)
            if (f->Name[nameLen - 1] == '/')
            {
              fileName = f->Name + nameLen;
              break;
            }
            
          outputHandle = 
          #ifdef USE_WINDOWS_FUNCTIONS
            CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, 
                NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
          if (outputHandle == INVALID_HANDLE_VALUE)
          #else
          fopen(fileName, "wb+");
          if (outputHandle == 0)
          #endif
          {
            PrintError("can not open output file");
            res = SZE_FAIL;
            break;
          }
          processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
          if (processedSize != outSizeProcessed)
          {
            PrintError("can not write output file");
            res = SZE_FAIL;
            break;
          }
          if (MyCloseFile(outputHandle))
          {
            PrintError("can not close output file");
            res = SZE_FAIL;
            break;
          }
        }
        printf("\n");
      }
      allocImp.Free(outBuffer);
    }
    else
    {
      PrintError("incorrect command");
      res = SZE_FAIL;
    }
  }
  SzArDbExFree(&db, allocImp.Free);

  MyCloseFile(archiveStream.File);
  if (res == SZ_OK)
  {
    printf("\nEverything is Ok\n");
    return 0;
  }
  if (res == (SZ_RESULT)SZE_NOTIMPL)
    PrintError("decoder doesn't support this archive");
  else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
    PrintError("can not allocate memory");
  else if (res == (SZ_RESULT)SZE_CRC_ERROR)
    PrintError("CRC error");
  else     
    printf("\nERROR #%d\n", res);
  return 1;
}