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; } } }
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; }
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; }
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; } }
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 */
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; }
/* 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; }
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; }
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; }
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; }
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; }