C7zip::C7zip (LPCSTR FileName) : m_FileSize(0), m_CurrentFile(-1), m_blockIndex(0xFFFFFFFF), m_outBuffer(0), m_outBufferSize(0), m_NotfyCallback(NotfyCallbackDefault), m_NotfyCallbackInfo(NULL), m_db(NULL), m_Opened(false) { memset(&m_FileName,0,sizeof(m_FileName)); memset(&m_archiveLookStream,0,sizeof(m_archiveLookStream)); m_db = new CSzArEx; memset(m_db,0,sizeof(CSzArEx)); m_archiveStream.s.Read = SzFileReadImp; m_archiveStream.s.Seek = SzFileSeekImp; m_allocImp.Alloc = AllocAllocImp; m_allocImp.Free = AllocFreeImp; m_allocTempImp.Alloc = AllocAllocImp; m_allocTempImp.Free = AllocFreeImp; InFile_Open(&m_archiveStream.file,FileName); if (m_archiveStream.file.handle == INVALID_HANDLE_VALUE) { //PrintError("can not open input file"); return; } m_FileSize = GetFileSize(m_archiveStream.file.handle,NULL); char drive[_MAX_DRIVE] ,dir[_MAX_DIR], ext[_MAX_EXT]; _splitpath( FileName, drive, dir, m_FileName, ext ); CrcGenerateTable(); SzArEx_Init(m_db); LookToRead_Init(&m_archiveLookStream); LookToRead_CreateVTable(&m_archiveLookStream, False); m_archiveLookStream.realStream = &m_archiveStream.s; SRes res = SzArEx_Open(m_db, &m_archiveLookStream.s, &m_allocImp, &m_allocTempImp); if (res == SZ_OK) { m_Opened = true; } else { //SzArEx_Open will delete the passed db if it fails m_db = NULL; } }
ar_archive *ar_open_7z_archive(ar_stream *stream) { ar_archive *ar; ar_archive_7z *_7z; SRes res; if (!ar_seek(stream, 0, SEEK_SET)) return NULL; ar = ar_open_archive(stream, sizeof(ar_archive_7z), _7z_close, _7z_parse_entry, _7z_get_name, _7z_uncompress, NULL, 0); if (!ar) return NULL; _7z = (ar_archive_7z *)ar; CSeekStream_CreateVTable(&_7z->in_stream, stream); LookToRead_CreateVTable(&_7z->look_stream, False); _7z->look_stream.realStream = &_7z->in_stream.super; LookToRead_Init(&_7z->look_stream); #ifdef USE_7Z_CRC32 CrcGenerateTable(); #endif SzArEx_Init(&_7z->data); res = SzArEx_Open(&_7z->data, &_7z->look_stream.s, &gSzAlloc, &gSzAlloc); if (res != SZ_OK) { if (res != SZ_ERROR_NO_ARCHIVE) warn("Invalid 7z archive (failed with error %d)", res); free(ar); return NULL; } return ar; }
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hInstNULL, LPSTR lpszCmdLine, int nCmdShow) { setlocale(LC_ALL, "Russian"); CrcGenerateTable(); options_load(); dialog_main(hInstance, NULL); return 0; }
Memory* ElfInterface::CreateGnuDebugdataMemory() { if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) { return nullptr; } // TODO: Only call these initialization functions once. CrcGenerateTable(); Crc64GenerateTable(); std::vector<uint8_t> src(gnu_debugdata_size_); if (!memory_->Read(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) { gnu_debugdata_offset_ = 0; gnu_debugdata_size_ = static_cast<uint64_t>(-1); return nullptr; } ISzAlloc alloc; CXzUnpacker state; alloc.Alloc = [](void*, size_t size) { return malloc(size); }; alloc.Free = [](void*, void* ptr) { return free(ptr); }; XzUnpacker_Construct(&state, &alloc); std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer); int return_val; size_t src_offset = 0; size_t dst_offset = 0; ECoderStatus status; dst->Resize(5 * gnu_debugdata_size_); do { size_t src_remaining = src.size() - src_offset; size_t dst_remaining = dst->Size() - dst_offset; if (dst_remaining < 2 * gnu_debugdata_size_) { dst->Resize(dst->Size() + 2 * gnu_debugdata_size_); dst_remaining += 2 * gnu_debugdata_size_; } return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset], &src_remaining, CODER_FINISH_ANY, &status); src_offset += src_remaining; dst_offset += dst_remaining; } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED); XzUnpacker_Free(&state); if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) { gnu_debugdata_offset_ = 0; gnu_debugdata_size_ = static_cast<uint64_t>(-1); return nullptr; } // Shrink back down to the exact size. dst->Resize(dst_offset); return dst.release(); }
value ml_sevenzip_init(value unit) { CAMLparam1 (unit); CrcGenerateTable(); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CAMLreturn (Val_unit); }
C7zArchive(FileReader *file) : ArchiveStream(file) { if (g_CrcTable[1] == 0) { CrcGenerateTable(); } file->Seek(0, SEEK_SET); LookToRead_CreateVTable(&LookStream, false); LookStream.realStream = &ArchiveStream.s; LookToRead_Init(&LookStream); SzArEx_Init(&DB); BlockIndex = 0xFFFFFFFF; OutBuffer = NULL; OutBufferSize = 0; }
struct VDir* VDirOpen7z(const char* path, int flags) { if (flags & O_WRONLY || flags & O_CREAT) { return 0; } struct VDir7z* vd = malloc(sizeof(struct VDir7z)); // What does any of this mean, Igor? if (InFile_Open(&vd->archiveStream.file, path)) { free(vd); return 0; } vd->allocImp.Alloc = SzAlloc; vd->allocImp.Free = SzFree; vd->allocTempImp.Alloc = SzAllocTemp; vd->allocTempImp.Free = SzFreeTemp; FileInStream_CreateVTable(&vd->archiveStream); LookToRead_CreateVTable(&vd->lookStream, False); vd->lookStream.realStream = &vd->archiveStream.s; LookToRead_Init(&vd->lookStream); CrcGenerateTable(); SzArEx_Init(&vd->db); SRes res = SzArEx_Open(&vd->db, &vd->lookStream.s, &vd->allocImp, &vd->allocTempImp); if (res != SZ_OK) { free(vd); return 0; } vd->dirent.index = 0; vd->dirent.utf8 = 0; vd->dirent.vd = vd; vd->dirent.d.name = _vde7zName; vd->d.close = _vd7zClose; vd->d.rewind = _vd7zRewind; vd->d.listNext = _vd7zListNext; vd->d.openFile = _vd7zOpenFile; return &vd->d; }
static void initArchives() { CrcGenerateTable(); registerArc7z(); registerCodecBCJ(); registerCodecBCJ2(); registerCodecLZMA(); registerCodecLZMA2(); registerCodecDelta(); registerCodecBranch(); registerCodecByteSwap(); NArchive::NXz::registerArcxz(); NArchive::NSplit::registerArcSplit(); NArchive::NLzma::NLzmaAr::registerArcLzma(); NArchive::NLzma::NLzma86Ar::registerArcLzma86(); }
static int sevenzip_parse_file_init(file_archive_transfer_t *state, const char *file) { struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)sevenzip_stream_new(); if (state->archive_size < SEVENZIP_MAGIC_LEN) goto error; if (memcmp(state->data, SEVENZIP_MAGIC, SEVENZIP_MAGIC_LEN) != 0) goto error; state->stream = sevenzip_context; /* could not open 7zip archive? */ if (InFile_Open(&sevenzip_context->archiveStream.file, file)) goto error; FileInStream_CreateVTable(&sevenzip_context->archiveStream); LookToRead_CreateVTable(&sevenzip_context->lookStream, False); sevenzip_context->lookStream.realStream = &sevenzip_context->archiveStream.s; LookToRead_Init(&sevenzip_context->lookStream); CrcGenerateTable(); SzArEx_Init(&sevenzip_context->db); if (SzArEx_Open(&sevenzip_context->db, &sevenzip_context->lookStream.s, &sevenzip_context->allocImp, &sevenzip_context->allocTempImp) != SZ_OK) goto error; return 0; error: if (sevenzip_context) sevenzip_stream_free(sevenzip_context); return -1; }
bool SzArchive::Open(const char* path) { SzArEx_Init(&szarchive); if (InFile_Open(&archiveStream.file, path)) return false; FileInStream_CreateVTable(&archiveStream); LookToRead2_CreateVTable(&lookStream, false); lookStream.buf = (Byte *)ISzAlloc_Alloc(&g_Alloc, kInputBufSize); if (lookStream.buf == NULL) return false; lookStream.bufSize = kInputBufSize; lookStream.realStream = &archiveStream.vt; LookToRead2_Init(&lookStream); if (!crc_tables_generated) { CrcGenerateTable(); crc_tables_generated = true; } SRes res = SzArEx_Open(&szarchive, &lookStream.vt, &g_Alloc, &g_Alloc); return (res == SZ_OK); }
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix) { CMemInStream memStream; MemInStream_Init(&memStream, payload, payloadSize); CrcGenerateTable(); ISzAlloc alloc = { SzAlloc, SzFree }; CSzArEx db; SzArEx_Init(&db); SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc); if (res != SZ_OK) { SzArEx_Free(&db, &alloc); return; } WCHAR buffer[MAX_PATH]; UInt32 blockIndex = 0xFFFFFFFF; Byte* outBuffer = 0; size_t outBufferSize = 0; for (UInt32 i = 0; i < db.db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem* f = db.db.Files + i; SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer); WCHAR* destPath = buffer; if (wcsncmp(destPath, prefix, 3) == 0 || wcsncmp(destPath, L"ALL", 3) == 0) { // Skip the prefix (X64/X32/ALL) and the path separater. destPath += 4; } else { // This file isn't for this arch. continue; } if (!f->IsDir) { res = SzArEx_Extract( &db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &alloc, &alloc); if (res != SZ_OK) { break; } } for (size_t j = 0; destPath[j] != L'\0'; ++j) { if (destPath[j] == L'/') { destPath[j] = L'\0'; CreateDirectory(destPath, NULL); destPath[j] = CHAR_PATH_SEPARATOR; } } if (f->IsDir) { CreateDirectory(destPath, NULL); continue; } CSzFile outFile; if (OutFile_OpenW(&outFile, destPath)) { res = SZ_ERROR_FAIL; break; } size_t processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { res = SZ_ERROR_FAIL; break; } if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib); } IAlloc_Free(&alloc, outBuffer); SzArEx_Free(&db, &alloc); if (res == SZ_OK) { // Success. } }
int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; UInt16 *temp = NULL; size_t tempSize = 0; // UInt32 parents[NUM_PARENTS_MAX]; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); if (numargs == 1) { printf( "Usage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full paths\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; #endif allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; #ifdef UNDER_CE if (InFile_OpenW(&archiveStream.file, L"\test.7z")) #else if (InFile_Open(&archiveStream.file, args[2])) #endif { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, fullPaths = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) { } else if (strcmp(command, "x") == 0) { fullPaths = 1; } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } if (res == SZ_OK) { 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) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; // const CSzFileItem *f = db.Files + i; size_t len; unsigned isDir = SzArEx_IsDir(&db, i); if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); // len = SzArEx_GetFullNameLen(&db, i); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); if (!temp) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); /* if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) { res = SZ_ERROR_FAIL; break; } */ if (listCommand) { char attr[8], s[32], t[32]; UInt64 fileSize; GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); fileSize = SzArEx_GetFileSize(&db, i); UInt64ToStr(fileSize, s); if (SzBitWithVals_Check(&db.MTime, i)) ConvertFileTimeToString(&db.MTime.Vals[i], t); else { size_t j; for (j = 0; j < 19; j++) t[j] = ' '; t[j] = '\0'; } printf("%s %s %10s ", t, attr, s); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) printf("/"); printf("\n"); continue; } fputs(testCommand ? "Testing ": "Extracting ", stdout); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) printf("/"); else { res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } if (!testCommand) { CSzFile outFile; size_t processedSize; size_t j; UInt16 *name = (UInt16 *)temp; const UInt16 *destPath = (const UInt16 *)name; for (j = 0; name[j] != 0; j++) if (name[j] == '/') { if (fullPaths) { name[j] = 0; MyCreateDir(name); name[j] = CHAR_PATH_SEPARATOR; } else destPath = name + j + 1; } if (isDir) { MyCreateDir(destPath); printf("\n"); continue; } else if (OutFile_OpenUtf16(&outFile, destPath)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) SetFileAttributesW(destPath, db.Attribs.Vals[i]); #endif } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } } SzArEx_Free(&db, &allocImp); SzFree(NULL, temp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; }
ASM(LONG) sz_GetInfo(REG(a0, struct xadArchiveInfo *ai), REG(a6, struct xadMasterBase *xadMasterBase)) #endif { #ifdef __amigaos4__ IExec = (struct ExecIFace *)(*(struct ExecBase **)4)->MainInterface; newlibbase = OpenLibrary("newlib.library", 52); if(newlibbase) INewlib = GetInterface(newlibbase, "main", 1, NULL); #elif defined(__AROS__) if(!(aroscbase = OpenLibrary("arosc.library", 41))) return(XADERR_RESOURCE); #else SysBase = *(struct ExecBase **)4; #endif ai->xai_PrivateClient = xadAllocVec(sizeof(struct xad7zprivate),MEMF_PRIVATE | MEMF_CLEAR); struct xad7zprivate *xad7z = ai->xai_PrivateClient; struct xadFileInfo *fi; long err=XADERR_OK; long res=SZ_OK; size_t namelen; UBYTE *namebuf; // was UWORD CFileXadInStream *archiveStream = &xad7z->archiveStream; CSzArEx *db = &xad7z->db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ CLookToRead *lookStream = &xad7z->lookStream; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; archiveStream->ai = ai; #ifdef __amigaos4__ archiveStream->IxadMaster = IxadMaster; #else archiveStream->xadMasterBase = xadMasterBase; #endif archiveStream->InStream.Read = SzFileReadImp; archiveStream->InStream.Seek = SzFileSeekImp; if(namebuf = AllocVec(1024, MEMF_PRIVATE)) { LookToRead_CreateVTable(lookStream, False); lookStream->realStream = (ISeekInStream *)&archiveStream->InStream; LookToRead_Init(lookStream); xad7z->blockIndex = 0xfffffff; xad7z->outBuffer = 0; xad7z->outBufferSize = 0; CrcGenerateTable(); SzArEx_Init(db); res = SzArEx_Open(db, &lookStream->s, &allocImp, &allocTempImp); if(res == SZ_OK) { UInt32 i; for (i = 0; i < db->db.NumFiles; i++) { fi = (struct xadFileInfo *) xadAllocObjectA(XADOBJ_FILEINFO, NULL); if (!fi) return(XADERR_NOMEMORY); CSzFileItem *f = db->db.Files + i; fi->xfi_DataPos = 0; //ai->xai_InPos; // i fi->xfi_Size = f->Size; namelen = SzArEx_GetFileNameUtf16(db, i, namebuf); // & if (!(fi->xfi_FileName = xadConvertName(CHARSET_HOST, #if defined(__AROS__) && (AROS_BIG_ENDIAN == 0) XAD_CHARACTERSET, CHARSET_UNICODE_UCS2_LITTLEENDIAN, #else XAD_CHARACTERSET, CHARSET_UNICODE_UCS2_BIGENDIAN, #endif XAD_STRINGSIZE, namelen, XAD_CSTRING, namebuf, // no * TAG_DONE))) return(XADERR_NOMEMORY); xadConvertDates(XAD_DATEAMIGA,ConvertFileTime(&f->MTime), XAD_GETDATEXADDATE,&fi->xfi_Date, TAG_DONE); fi->xfi_CrunchSize = 0; //(long) (db->Database.PackSizes[i] << 32); //fi->xfi_Size; fi->xfi_Flags = 0; if(f->IsDir) { fi->xfi_Flags |= XADFIF_DIRECTORY; } if ((err = xadAddFileEntryA(fi, ai, NULL))) return(XADERR_NOMEMORY); } } FreeVec(namebuf); } return(sztoxaderr(res)); }
struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;
int SzExtractFromBuf(const void* pBuf, unsigned int nBufLength, wchar_t* cUnPackPath, DWORD dwPathLength) { if(pBuf==NULL || nBufLength<=0) return 1; SRes res = SZ_OK; CBufInStream archiveStream; CLookToRead lookStream; CSzArEx db; ISzAlloc allocImp; ISzAlloc allocTempImp; const char *errorMessage = NULL; wchar_t path[MAX_PATH * 3 + 2] = {0}; size_t pathLen = wcslen(cUnPackPath); wcscpy_s(path,MAX_PATH * 3 + 2, cUnPackPath); if (cUnPackPath[pathLen - 1] != '\\') { wcscat_s(path, L"\\"); pathLen = wcslen(path); } CrcGenerateTable(); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; BufInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); if (InBuf_Init(&archiveStream.buf, pBuf, nBufLength) != 0) { errorMessage = "can not open input file"; res = SZ_ERROR_FAIL; } else { UInt64 pos = 0; if (!FindSignature(&archiveStream.buf, &pos)) res = SZ_ERROR_FAIL; else if (InBuf_Seek(&archiveStream.buf, (Int64 *)&pos, SZ_SEEK_SET) != 0) res = SZ_ERROR_FAIL; if (res != 0) errorMessage = "Can't find 7z archive"; } if (res == SZ_OK) { lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); } SzArEx_Init(&db); if (res == SZ_OK) { res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); } if (res == SZ_OK) { UInt32 executeFileIndex = (UInt32)(Int32)-1; UInt32 minPrice = 1 << 30; UInt32 i; 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) */ for (i = 0; i < db.db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem *f = db.db.Files + i; size_t len; wchar_t *temp; len = SzArEx_GetFileNameUtf16(&db, i, NULL); if (len >= MAX_PATH) { res = SZ_ERROR_FAIL; break; } temp = path + pathLen; SzArEx_GetFileNameUtf16(&db, i, reinterpret_cast<UInt16*>(temp)); { res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } { CSzFile outFile; size_t processedSize; size_t j; size_t nameStartPos = 0; for (j = 0; temp[j] != 0; j++) { if (temp[j] == '/') { temp[j] = 0; MyCreateDir(path); temp[j] = CHAR_PATH_SEPARATOR; nameStartPos = j + 1; } } if (f->IsDir) { MyCreateDir(path); continue; } else { if (DoesFileOrDirExist(path)) { errorMessage = "Duplicate file"; res = SZ_ERROR_FAIL; break; } if (OutFile_OpenW(&outFile, path)) { errorMessage = "Can't open output file"; res = SZ_ERROR_FAIL; break; } } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { errorMessage = "Can't write output file"; res = SZ_ERROR_FAIL; } #ifdef USE_WINDOWS_FILE if (f->MTimeDefined) { FILETIME mTime; mTime.dwLowDateTime = f->MTime.Low; mTime.dwHighDateTime = f->MTime.High; SetFileTime(outFile.handle, NULL, NULL, &mTime); } #endif { SRes res2 = File_Close(&outFile); if (res != SZ_OK) break; if (res2 != SZ_OK) { res = res2; break; } } #ifdef USE_WINDOWS_FILE if (f->AttribDefined) SetFileAttributesW(path, f->Attrib); #endif } } IAlloc_Free(&allocImp, outBuffer); } SzArEx_Free(&db, &allocImp); if (res == SZ_OK) { _tcscpy_s(cUnPackPath, dwPathLength, path); return 0; } else return 1; }
_7z_error _7z_file_open(const char *filename, _7z_file **_7z) { file_error err; _7z_error _7zerr = _7ZERR_NONE; _7z_file *new_7z; char *string; int cachenum; SRes res; /* ensure we start with a NULL result */ *_7z = NULL; /* see if we are in the cache, and reopen if so */ for (cachenum = 0; cachenum < ARRAY_LENGTH(_7z_cache); cachenum++) { _7z_file *cached = _7z_cache[cachenum]; /* if we have a valid entry and it matches our filename, use it and remove from the cache */ if (cached != NULL && cached->filename != NULL && strcmp(filename, cached->filename) == 0) { *_7z = cached; _7z_cache[cachenum] = NULL; return _7ZERR_NONE; } } /* allocate memory for the _7z_file structure */ new_7z = (_7z_file *)malloc(sizeof(*new_7z)); if (new_7z == NULL) return _7ZERR_OUT_OF_MEMORY; memset(new_7z, 0, sizeof(*new_7z)); new_7z->inited = false; new_7z->archiveStream.file._7z_currfpos = 0; err = osd_open(filename, OPEN_FLAG_READ, &new_7z->archiveStream.file._7z_osdfile, &new_7z->archiveStream.file._7z_length); if (err != FILERR_NONE) { _7zerr = _7ZERR_FILE_ERROR; goto error; } new_7z->allocImp.Alloc = SZipAlloc; new_7z->allocImp.Free = SZipFree; new_7z->allocTempImp.Alloc = SZipAlloc; new_7z->allocTempImp.Free = SZipFree; if (InFile_Open(&new_7z->archiveStream.file, filename)) { _7zerr = _7ZERR_FILE_ERROR; goto error; } FileInStream_CreateVTable(&new_7z->archiveStream); LookToRead_CreateVTable(&new_7z->lookStream, False); new_7z->lookStream.realStream = &new_7z->archiveStream.s; LookToRead_Init(&new_7z->lookStream); CrcGenerateTable(); SzArEx_Init(&new_7z->db); new_7z->inited = true; res = SzArEx_Open(&new_7z->db, &new_7z->lookStream.s, &new_7z->allocImp, &new_7z->allocTempImp); if (res != SZ_OK) { _7zerr = _7ZERR_FILE_ERROR; goto error; } new_7z->blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ new_7z->outBuffer = 0; /* it must be 0 before first call for each new archive. */ new_7z->outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ /* make a copy of the filename for caching purposes */ string = (char *)malloc(strlen(filename) + 1); if (string == NULL) { _7zerr = _7ZERR_OUT_OF_MEMORY; goto error; } strcpy(string, filename); new_7z->filename = string; *_7z = new_7z; return _7ZERR_NONE; error: free__7z_file(new_7z); return _7zerr; }
static struct string_list *compressed_7zip_file_list_new( const char *path, const char* ext) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; ISzAlloc allocImp; ISzAlloc allocTempImp; size_t temp_size = 0; struct string_list *list = NULL; /* These are the allocation routines - currently using * the non-standard 7zip choices. */ allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; if (InFile_Open(&archiveStream.file, path)) { RARCH_ERR("Could not open %s as 7z archive.\n",path); return NULL; } list = string_list_new(); if (!list) { File_Close(&archiveStream.file); return NULL; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); CrcGenerateTable(); SzArEx_Init(&db); if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK) { uint32_t i; struct string_list *ext_list = ext ? string_split(ext, "|"): NULL; SRes res = SZ_OK; uint16_t *temp = NULL; for (i = 0; i < db.db.NumFiles; i++) { union string_list_elem_attr attr; char infile[PATH_MAX_LENGTH]; const char *file_ext = NULL; size_t len = 0; bool supported_by_core = false; const CSzFileItem *f = db.db.Files + i; /* we skip over everything, which is a directory. */ if (f->IsDir) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); if (len > temp_size) { free(temp); temp_size = len; temp = (uint16_t *)malloc(temp_size * sizeof(temp[0])); if (temp == 0) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); res = utf16_to_char_string(temp, infile, sizeof(infile)) ? SZ_OK : SZ_ERROR_FAIL; file_ext = path_get_extension(infile); if (string_list_find_elem_prefix(ext_list, ".", file_ext)) supported_by_core = true; /* * Currently we only support files without subdirs in the archives. * Folders are not supported (differences between win and lin. * Archives within archives should imho never be supported. */ if (!supported_by_core) continue; attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; if (!string_list_append(list, infile, attr)) { res = SZ_ERROR_MEM; break; } } string_list_free(ext_list); free(temp); if (res != SZ_OK) { /* Error handling */ RARCH_ERR("Failed to open compressed_file: \"%s\"\n", path); string_list_free(list); list = NULL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); return list; }
bool Qt7zPackage::open() { if (m_p->m_isOpen) { return false; } SRes res; UInt16 *temp = NULL; size_t tempSize = 0; if (InFile_Open(&(m_p->m_archiveStream.file), m_p->m_packagePath.toUtf8().data())) { qDebug() << "Can not open file: " << m_p->m_packagePath; m_p->m_isOpen = false; return false; } FileInStream_CreateVTable(&(m_p->m_archiveStream)); LookToRead_CreateVTable(&(m_p->m_lookStream), False); m_p->m_lookStream.realStream = &(m_p->m_archiveStream.s); LookToRead_Init(&(m_p->m_lookStream)); CrcGenerateTable(); SzArEx_Init(&(m_p->m_db)); res = SzArEx_Open(&(m_p->m_db), &(m_p->m_lookStream.s), &(m_p->m_allocImp), &(m_p->m_allocTempImp)); if (res == SZ_OK) { for (UInt32 i = 0; i < m_p->m_db.db.NumFiles; i++) { size_t len = SzArEx_GetFileNameUtf16(&(m_p->m_db), i, NULL); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); if (temp == 0) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&(m_p->m_db), i, temp); // TODO: Codec? QString fileName = QString::fromUtf16(temp); m_p->m_fileNameList << fileName; const CSzFileItem &fileItem = m_p->m_db.db.Files[i]; Qt7zFileInfo fileInfo; fileInfo.fileName = fileName; fileInfo.arcName = m_p->m_packagePath; fileInfo.size = fileItem.Size; fileInfo.isDir = fileItem.IsDir; fileInfo.isCrcDefined = fileItem.CrcDefined; fileInfo.crc = fileItem.Crc; m_p->m_fileInfoList << fileInfo; if (res != SZ_OK) break; } } SzFree(NULL, temp); if (res == SZ_OK) { m_p->m_isOpen = true; return true; } else { m_p->m_isOpen = false; return false; } }
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; }
int auxio_load_archive(const char *filename, unsigned char **dataout, int *datasize, int *dataoffset, const char *filetoload, char *outname) { FILE *f; unsigned char idbuf[4]; int filesFound = 0; std::vector<char *> filelist; // list of files we can load in this archive // default case: outname is filename if (outname) { strcpy(outname, filename); } f = fopen(filename, "rb"); if (!f) { return 0; // no good } fread(idbuf, 4, 1, f); fclose(f); // printf("ID bytes %c %c %x %x\n", idbuf[0], idbuf[1], idbuf[2], idbuf[3]); if ((idbuf[0] == 'P') && (idbuf[1] == 'K') && (idbuf[2] == 0x03) && (idbuf[3] == 0x04)) { // it's zip unzFile zipArchive; char file_name[1024]; unz_file_info info; int nlen; int ret = 0; zipArchive = unzOpen(filename); if (!zipArchive) { return 0; } unzGoToFirstFile(zipArchive); for (;;) { if (unzGetCurrentFileInfo(zipArchive, &info, file_name, 1024, NULL, 0, NULL, 0) == UNZ_OK) { if (filetoload != NULL) { if (!strcasecmp(filetoload, file_name)) { int length; unsigned char *buffer; unzOpenCurrentFile(zipArchive); length = info.uncompressed_size; buffer = (unsigned char *)malloc(length); ret = unzReadCurrentFile(zipArchive, buffer, length); if (ret != length) { free(buffer); return 0; } unzCloseCurrentFile(zipArchive); unzClose(zipArchive); *datasize = length; *dataout = buffer; *dataoffset = 0; return 1; } } else { if (checkExtension(file_name)) { char *tmpstr; tmpstr = (char *)malloc(strlen(file_name)+1); strcpy(tmpstr, file_name); // add to the file list filelist.push_back(tmpstr); filesFound++; } } } else { break; } ret = unzGoToNextFile(zipArchive); if (ret == UNZ_END_OF_LIST_OF_FILE) { break; } if (ret != UNZ_OK) { unzClose(zipArchive); return 0; } } unzClose(zipArchive); } else if ((idbuf[0] == '7') && (idbuf[1] == 'z') && (idbuf[2] == 0xbc) && (idbuf[3] == 0xaf)) { // it's 7zip CFileInStream archiveStream; SRes res; CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ archiveStream.File = fopen(filename, "rb"); if (!archiveStream.File) { return 0; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; // init 7zip internals CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &archiveStream.InStream, &allocImp, &allocTempImp); if (res == SZ_OK) { int i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *item = db.db.Files + i; if (!item->IsDirectory) { if (filetoload != NULL) { if (!strcasecmp(filetoload, item->Name)) { 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) */ size_t offset; size_t outSizeProcessed; res = SzAr_Extract(&db, &archiveStream.InStream, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res == SZ_OK) { SzArEx_Free(&db, &allocImp); fclose(archiveStream.File); *datasize = (int)outBufferSize; *dataout = (unsigned char *)outBuffer; *dataoffset = (int)offset; return 1; } else { std::cout << "Error extracting 7zip!\n"; } } } if (checkExtension(item->Name)) { char *tmpstr; tmpstr = (char *)malloc(strlen(item->Name)+1); strcpy(tmpstr, item->Name); // add to the file list filelist.push_back(tmpstr); filesFound++; } } } SzArEx_Free(&db, &allocImp); fclose(archiveStream.File); } } else if ((idbuf[0] == 'R') && (idbuf[1] == 'a') && (idbuf[2] == 'r') && (idbuf[3] == '!')) { // it's rar } // if we found any files and weren't forced to load them, handle accordingly if (filesFound) { // only 1 file found, just run it if (filesFound == 1) { char fname[512]; strcpy(fname, filelist[0]); free(filelist[0]); filelist.clear(); strcpy(outname, fname); return auxio_load_archive(filename, dataout, datasize, dataoffset, fname, NULL); } else // multiple files we can handle found, give the user a choice { int sel; char fname[512]; filepicker = create_archselect(); tree = lookup_widget(filepicker, "archtree"); gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW (tree), FALSE); g_signal_connect(G_OBJECT(tree), "button_press_event", G_CALLBACK(check_list_double), NULL); // set up our tree store treestore = gtk_tree_store_new(1, G_TYPE_STRING); // attach the store to the tree gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(treestore)); // create a cell renderer using the stock text one renderer = gtk_cell_renderer_text_new(); // create a display column using the renderer column = gtk_tree_view_column_new_with_attributes ("NES file", renderer, "text", 0, NULL); // add the display column and renderer to the tree view gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); // get the selection object too selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); // add the filenames for (int fn = 0; fn < filelist.size(); fn++) { gtk_tree_store_insert(treestore, &treeiters[fn], NULL, 999999); gtk_tree_store_set(treestore, &treeiters[fn], 0, filelist[fn], -1); } gtk_widget_show(filepicker); run_picker = true; cancelled = false; while (run_picker) { gtk_main_iteration_do(FALSE); } sel = find_current_selection(); gtk_widget_destroy(filepicker); // was something picked? if ((sel != -1) && (!cancelled)) { strcpy(fname, filelist[sel]); } // free all the temp filenames for (int fn = 0; fn < filelist.size(); fn++) { free(filelist[fn]); } // and wipe the vector filelist.clear(); if ((sel != -1) && (!cancelled)) { if (outname) { strcpy(outname, fname); } return auxio_load_archive(filename, dataout, datasize, dataoffset, fname, NULL); } } } return 0; }
int main(int argc, char *argv[]) { struct timeval start_time, end_time; struct sigaction handler; double seconds,total_time; // for timers bool lrzcat = false; int c, i; int hours,minutes; extern int optind; char *eptr; /* for environment */ control = &base_control; initialise_control(control); if (strstr(argv[0], "lrunzip")) control->flags |= FLAG_DECOMPRESS; else if (strstr(argv[0], "lrzcat")) { control->flags |= FLAG_DECOMPRESS | FLAG_STDOUT; lrzcat = true; } /* generate crc table */ CrcGenerateTable(); /* Get Preloaded Defaults from lrzip.conf * Look in ., $HOME/.lrzip/, /etc/lrzip. * If LRZIP=NOCONFIG is set, then ignore config */ eptr = getenv("LRZIP"); if (eptr == NULL) read_config(control); else if (!strstr(eptr,"NOCONFIG")) read_config(control); while ((c = getopt_long(argc, argv, "bcdDefghHiklL:nN:o:O:p:qS:tTUm:vVw:z?", long_options, &i)) != -1) { switch (c) { case 'b': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_BZIP2_COMPRESS; break; case 'c': control->flags |= FLAG_CHECK; control->flags |= FLAG_HASH; break; case 'd': control->flags |= FLAG_DECOMPRESS; break; case 'D': control->flags &= ~FLAG_KEEP_FILES; break; case 'e': control->flags |= FLAG_ENCRYPT; break; case 'f': control->flags |= FLAG_FORCE_REPLACE; break; case 'g': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_ZLIB_COMPRESS; break; case 'h': case '?': usage(); return -1; case 'H': control->flags |= FLAG_HASH; break; case 'i': control->flags |= FLAG_INFO; break; case 'k': control->flags |= FLAG_KEEP_BROKEN; break; case 'l': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_LZO_COMPRESS; break; case 'L': control->compression_level = atoi(optarg); if (control->compression_level < 1 || control->compression_level > 9) failure("Invalid compression level (must be 1-9)\n"); break; case 'm': control->ramsize = atol(optarg) * 1024 * 1024 * 100; break; case 'n': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_NO_COMPRESS; break; case 'N': control->nice_val = atoi(optarg); if (control->nice_val < -20 || control->nice_val > 19) failure("Invalid nice value (must be -20..19)\n"); break; case 'o': if (control->outdir) failure("Cannot have -o and -O together\n"); if (unlikely(STDOUT)) failure("Cannot specify an output filename when outputting to stdout\n"); control->outname = optarg; control->suffix = ""; break; case 'O': if (control->outname) /* can't mix -o and -O */ failure("Cannot have options -o and -O together\n"); if (unlikely(STDOUT)) failure("Cannot specify an output directory when outputting to stdout\n"); control->outdir = malloc(strlen(optarg) + 2); if (control->outdir == NULL) fatal("Failed to allocate for outdir\n"); strcpy(control->outdir,optarg); if (strcmp(optarg+strlen(optarg) - 1, "/")) /* need a trailing slash */ strcat(control->outdir, "/"); break; case 'p': control->threads = atoi(optarg); if (control->threads < 1) failure("Must have at least one thread\n"); break; case 'q': control->flags &= ~FLAG_SHOW_PROGRESS; break; case 'S': if (control->outname) failure("Specified output filename already, can't specify an extension.\n"); if (unlikely(STDOUT)) failure("Cannot specify a filename suffix when outputting to stdout\n"); control->suffix = optarg; break; case 't': if (control->outname) failure("Cannot specify an output file name when just testing.\n"); if (!KEEP_FILES) failure("Doubt that you want to delete a file when just testing.\n"); control->flags |= FLAG_TEST_ONLY; break; case 'T': control->flags &= ~FLAG_THRESHOLD; break; case 'U': control->flags |= FLAG_UNLIMITED; break; case 'v': /* set verbosity flag */ if (!(control->flags & FLAG_VERBOSITY) && !(control->flags & FLAG_VERBOSITY_MAX)) control->flags |= FLAG_VERBOSITY; else if ((control->flags & FLAG_VERBOSITY)) { control->flags &= ~FLAG_VERBOSITY; control->flags |= FLAG_VERBOSITY_MAX; } break; case 'V': print_output("lrzip version %s\n", PACKAGE_VERSION); exit(0); break; case 'w': control->window = atol(optarg); break; case 'z': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_ZPAQ_COMPRESS; break; } } argc -= optind; argv += optind; if (control->outname && argc > 1) failure("Cannot specify output filename with more than 1 file\n"); if (VERBOSE && !SHOW_PROGRESS) { print_err("Cannot have -v and -q options. -v wins.\n"); control->flags |= FLAG_SHOW_PROGRESS; } if (UNLIMITED && control->window) { print_err("If -U used, cannot specify a window size with -w.\n"); control->window = 0; } if (argc < 1) control->flags |= FLAG_STDIN; if (UNLIMITED && STDIN) { print_err("Cannot have -U and stdin, unlimited mode disabled.\n"); control->flags &= ~FLAG_UNLIMITED; } setup_overhead(control); /* Set the main nice value to half that of the backend threads since * the rzip stage is usually the rate limiting step */ if (control->nice_val > 0 && !NO_COMPRESS) { if (unlikely(setpriority(PRIO_PROCESS, 0, control->nice_val / 2) == -1)) print_err("Warning, unable to set nice value\n"); } else { if (unlikely(setpriority(PRIO_PROCESS, 0, control->nice_val) == -1)) print_err("Warning, unable to set nice value\n"); } /* One extra iteration for the case of no parameters means we will default to stdin/out */ for (i = 0; i <= argc; i++) { if (i < argc) control->infile = argv[i]; else if (!(i == 0 && STDIN)) break; if (control->infile) { if ((strcmp(control->infile, "-") == 0)) control->flags |= FLAG_STDIN; else { struct stat infile_stat; stat(control->infile, &infile_stat); if (unlikely(S_ISDIR(infile_stat.st_mode))) failure("lrzip only works directly on FILES.\n" "Use lrztar or pipe through tar for compressing directories.\n"); } } if (INFO && STDIN) failure("Will not get file info from STDIN\n"); if ((control->outname && (strcmp(control->outname, "-") == 0)) || /* If no output filename is specified, and we're using * stdin, use stdout */ (!control->outname && STDIN) || lrzcat ) { control->flags |= FLAG_STDOUT; control->outFILE = stdout; control->msgout = stderr; register_outputfile(control, control->msgout); } if (lrzcat) { control->msgout = stderr; control->outFILE = stdout; register_outputfile(control, control->msgout); } if (!STDOUT) { control->msgout = stdout; register_outputfile(control, control->msgout); } if (STDIN) control->inFILE = stdin; /* Implement signal handler only once flags are set */ sigemptyset(&handler.sa_mask); handler.sa_flags = 0; handler.sa_handler = &sighandler; sigaction(SIGTERM, &handler, 0); sigaction(SIGINT, &handler, 0); if (!FORCE_REPLACE) { if (STDIN && isatty(fileno((FILE *)stdin))) { print_err("Will not read stdin from a terminal. Use -f to override.\n"); usage(); exit (1); } if (!TEST_ONLY && STDOUT && isatty(fileno((FILE *)stdout))) { print_err("Will not write stdout to a terminal. Use -f to override.\n"); usage(); exit (1); } } if (CHECK_FILE) { if (!DECOMPRESS) { print_err("Can only check file written on decompression.\n"); control->flags &= ~FLAG_CHECK; } else if (STDOUT) { print_err("Can't check file written when writing to stdout. Checking disabled.\n"); control->flags &= ~FLAG_CHECK; } } setup_ram(control); show_summary(); gettimeofday(&start_time, NULL); if (unlikely(STDIN && ENCRYPT)) failure("Unable to work from STDIN while reading password\n"); memcpy(&local_control, &base_control, sizeof(rzip_control)); if (DECOMPRESS || TEST_ONLY) decompress_file(&local_control); else if (INFO) get_fileinfo(&local_control); else compress_file(&local_control); /* compute total time */ gettimeofday(&end_time, NULL); total_time = (end_time.tv_sec + (double)end_time.tv_usec / 1000000) - (start_time.tv_sec + (double)start_time.tv_usec / 1000000); hours = (int)total_time / 3600; minutes = (int)(total_time / 60) % 60; seconds = total_time - hours * 3600 - minutes * 60; if (!INFO) print_progress("Total time: %02d:%02d:%05.2f\n", hours, minutes, seconds); } return 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; }
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; }
int MY_CDECL main(int numargs, char *args[]) { ISzAlloc allocImp; ISzAlloc allocTempImp; CFileInStream archiveStream; CLookToRead2 lookStream; CSzArEx db; SRes res; UInt16 *temp = NULL; size_t tempSize = 0; // UInt32 parents[NUM_PARENTS_MAX]; Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"); if (numargs == 1) { Print( "Usage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full paths\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; #endif allocImp = g_Alloc; allocTempImp = g_Alloc; #ifdef UNDER_CE if (InFile_OpenW(&archiveStream.file, L"\test.7z")) #else if (InFile_Open(&archiveStream.file, args[2])) #endif { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead2_CreateVTable(&lookStream, False); lookStream.buf = NULL; res = SZ_OK; { lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize); if (!lookStream.buf) res = SZ_ERROR_MEM; else { lookStream.bufSize = kInputBufSize; lookStream.realStream = &archiveStream.vt; LookToRead2_Init(&lookStream); } } CrcGenerateTable(); SzArEx_Init(&db); if (res == SZ_OK) { res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); } if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, fullPaths = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) { } else if (strcmp(command, "x") == 0) { fullPaths = 1; } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } if (res == SZ_OK) { 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) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; // const CSzFileItem *f = db.Files + i; size_t len; unsigned isDir = SzArEx_IsDir(&db, i); if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); // len = SzArEx_GetFullNameLen(&db, i); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); if (!temp) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); /* if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) { res = SZ_ERROR_FAIL; break; } */ if (listCommand) { char attr[8], s[32], t[32]; UInt64 fileSize; GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); fileSize = SzArEx_GetFileSize(&db, i); UInt64ToStr(fileSize, s, 10); if (SzBitWithVals_Check(&db.MTime, i)) ConvertFileTimeToString(&db.MTime.Vals[i], t); else { size_t j; for (j = 0; j < 19; j++) t[j] = ' '; t[j] = '\0'; } Print(t); Print(" "); Print(attr); Print(" "); Print(s); Print(" "); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) Print("/"); PrintLF(); continue; } Print(testCommand ? "Testing ": "Extracting "); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) Print("/"); else { res = SzArEx_Extract(&db, &lookStream.vt, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } if (!testCommand) { CSzFile outFile; size_t processedSize; size_t j; UInt16 *name = (UInt16 *)temp; const UInt16 *destPath = (const UInt16 *)name; for (j = 0; name[j] != 0; j++) if (name[j] == '/') { if (fullPaths) { name[j] = 0; MyCreateDir(name); name[j] = CHAR_PATH_SEPARATOR; } else destPath = name + j + 1; } if (isDir) { MyCreateDir(destPath); PrintLF(); continue; } else if (OutFile_OpenUtf16(&outFile, destPath)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } #ifdef USE_WINDOWS_FILE { FILETIME mtime, ctime; FILETIME *mtimePtr = NULL; FILETIME *ctimePtr = NULL; if (SzBitWithVals_Check(&db.MTime, i)) { const CNtfsFileTime *t = &db.MTime.Vals[i]; mtime.dwLowDateTime = (DWORD)(t->Low); mtime.dwHighDateTime = (DWORD)(t->High); mtimePtr = &mtime; } if (SzBitWithVals_Check(&db.CTime, i)) { const CNtfsFileTime *t = &db.CTime.Vals[i]; ctime.dwLowDateTime = (DWORD)(t->Low); ctime.dwHighDateTime = (DWORD)(t->High); ctimePtr = &ctime; } if (mtimePtr || ctimePtr) SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr); } #endif if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) { UInt32 attrib = db.Attribs.Vals[i]; /* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker. We remove posix bits, if we detect posix mode field */ if ((attrib & 0xF0000000) != 0) attrib &= 0x7FFF; SetFileAttributesW((LPCWSTR)destPath, attrib); } #endif } PrintLF(); } ISzAlloc_Free(&allocImp, outBuffer); } } SzFree(NULL, temp); SzArEx_Free(&db, &allocImp); ISzAlloc_Free(&allocImp, lookStream.buf); File_Close(&archiveStream.file); if (res == SZ_OK) { Print("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else { char s[32]; UInt64ToStr(res, s, 0); PrintError(s); } return 1; }
/* Extract the relative path (needle) from a 7z archive * (path) and allocate a buf for it to write it in. * If optional_outfile is set, extract to that instead * and don't allocate buffer. */ static int content_7zip_file_read( const char *path, const char *needle, void **buf, const char *optional_outfile) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; ISzAlloc allocImp; ISzAlloc allocTempImp; uint8_t *output = 0; long outsize = -1; /*These are the allocation routines. * Currently using the non-standard 7zip choices. */ allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; if (InFile_Open(&archiveStream.file, path)) { RARCH_ERR("Could not open %s as 7z archive\n.", path); return -1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); CrcGenerateTable(); SzArEx_Init(&db); if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK) { uint32_t i; bool file_found = false; uint16_t *temp = NULL; size_t temp_size = 0; uint32_t block_index = 0xFFFFFFFF; SRes res = SZ_OK; for (i = 0; i < db.db.NumFiles; i++) { size_t len; char infile[PATH_MAX_LENGTH]; size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem *f = db.db.Files + i; /* We skip over everything which is not a directory. * FIXME: Why continue then if f->IsDir is true?*/ if (f->IsDir) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); if (len > temp_size) { free(temp); temp_size = len; temp = (uint16_t *)malloc(temp_size * sizeof(temp[0])); if (temp == 0) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); res = utf16_to_char_string(temp, infile, sizeof(infile)) ? SZ_OK : SZ_ERROR_FAIL; if (string_is_equal(infile, needle)) { size_t output_size = 0; RARCH_LOG_OUTPUT("Opened archive %s. Now trying to extract %s\n", path, needle); /* C LZMA SDK does not support chunked extraction - see here: * sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/ * */ file_found = true; res = SzArEx_Extract(&db, &lookStream.s, i, &block_index, &output, &output_size, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; /* This goes to the error section. */ outsize = outSizeProcessed; if (optional_outfile != NULL) { const void *ptr = (const void*)(output + offset); if (!retro_write_file(optional_outfile, ptr, outsize)) { RARCH_ERR("Could not open outfilepath %s.\n", optional_outfile); res = SZ_OK; file_found = true; outsize = -1; } } else { /*We could either use the 7Zip allocated buffer, * or create our own and use it. * We would however need to realloc anyways, because RetroArch * expects a \0 at the end, therefore we allocate new, * copy and free the old one. */ *buf = malloc(outsize + 1); ((char*)(*buf))[outsize] = '\0'; memcpy(*buf,output + offset,outsize); } break; } } free(temp); IAlloc_Free(&allocImp, output); if (!(file_found && res == SZ_OK)) { /* Error handling */ if (!file_found) RARCH_ERR("File %s not found in %s\n", needle, path); RARCH_ERR("Failed to open compressed file inside 7zip archive.\n"); outsize = -1; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); return outsize; }
/*! * \brief * Decompresses a single file from a 7zip archive. * * \param archive_file * Path to the archive to extract the file from. * * \param file_name * The fine within the archive to extract. * * \param uncompressed_data * Reference parameter to set the uncompressed datas pointer to. * * \param uncompressed_data_size * Reference parameter to set the uncompressed data size to. * * \returns * Returns true if the decompresseion was successfull, otherwise returns false. * * Decompresses a single file from a 7zip archive. */ bool DecompressFileEntry(cstring archive_file, cstring file_name, byte*& uncompressed_data, size_t& uncompressed_data_size) { CFileInStream archive_stream; CLookToRead look_stream; CSzArEx archive_desc; SRes result; ISzAlloc alloc_imp; wchar_t wide_file_name[MAX_PATH] = L""; // open the archive for reading if (InFile_Open(&archive_stream.file, archive_file)) return false; // convert the search file name to a wide char string for comparison later if(-1 == swprintf_s(wide_file_name, MAX_PATH, L"%S", file_name)) return false; // set up the memory handling functions alloc_imp.Alloc = AllocFunc; alloc_imp.Free = FreeFunc; FileInStream_CreateVTable(&archive_stream); LookToRead_CreateVTable(&look_stream, False); look_stream.realStream = &archive_stream.s; LookToRead_Init(&look_stream); CrcGenerateTable(); SzArEx_Init(&archive_desc); result = SzArEx_Open(&archive_desc, &look_stream.s, &alloc_imp, &alloc_imp); if(result == SZ_OK) { int index = -1; // search for the file in the archive for (uint32 i = 0; (index == -1) && (i < archive_desc.db.NumFiles); i++) { if(archive_desc.db.Files[i].IsDir) continue; // get the name of the file in the archive uint32 name_length = SzArEx_GetFileNameUtf16(&archive_desc, i, NULL); wchar_t* archive_file_name = new wchar_t[name_length]; SzArEx_GetFileNameUtf16(&archive_desc, i, (UInt16*)archive_file_name); // compare the file names if(wcscmp(wide_file_name, archive_file_name) == 0) index = i; // delete allocated memory delete [] archive_file_name; } if(index > -1) { // file found, so decompress it result = Decompress(archive_stream, archive_desc, look_stream, index, uncompressed_data, uncompressed_data_size); } } SzArEx_Free(&archive_desc, &alloc_imp); File_Close(&archive_stream.file); return result == SZ_OK; }
CCRCTableInit() { CrcGenerateTable(); }
int main(int numargs, char *args[]) { FILE *archiveFile; CLookToRead archiveStream; CSzArEx db; int res; if (numargs != 3) { return 1; } if ((archiveFile = fopen(args[1], "r")) == NULL) { return 2; } if (!directoryExists(args[2])) { return 4; } int outPathLen = strlen(args[2]); int maxPathLen = 5; int pathLen; char *outputPath; outputPath = malloc(outPathLen + maxPathLen + 1); memcpy(outputPath, args[2], outPathLen); if (outputPath[outPathLen - 1] != '/') { outputPath[outPathLen] = '/'; outPathLen++; maxPathLen--; } archiveStream.file = &archiveFile; LookToRead_Init(&archiveStream); CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &archiveStream); if (res == SZ_OK) { UInt32 i; UInt32 blockIndex; Byte *outBuffer = 0; size_t outBufferSize; for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; pathLen = strlen(f->Name); if (pathLen > maxPathLen) { maxPathLen = pathLen * 2; outputPath = realloc(outputPath, outPathLen + maxPathLen + 1); } memcpy(outputPath + outPathLen, f->Name, pathLen + 1); mode_t fileMode; if (f->AttribDefined && f->Attrib & 0x8000) { fileMode = f->Attrib >> 16; } else {
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 APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, #ifdef UNDER_CE LPWSTR #else LPSTR #endif lpCmdLine, int nCmdShow) #endif { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res = SZ_OK; ISzAlloc allocImp; ISzAlloc allocTempImp; WCHAR sfxPath[MAX_PATH + 2]; WCHAR path[MAX_PATH * 3 + 2]; #ifndef UNDER_CE WCHAR workCurDir[MAX_PATH + 32]; #endif size_t pathLen; DWORD winRes; const wchar_t *cmdLineParams; const char *errorMessage = NULL; Bool useShellExecute = True; DWORD exitCode = 0; LoadSecurityDlls(); #ifdef _CONSOLE SetConsoleCtrlHandler(HandlerRoutine, TRUE); #else UNUSED_VAR(hInstance); UNUSED_VAR(hPrevInstance); UNUSED_VAR(lpCmdLine); UNUSED_VAR(nCmdShow); #endif CrcGenerateTable(); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); if (winRes == 0 || winRes > MAX_PATH) return 1; { cmdLineParams = GetCommandLineW(); #ifndef UNDER_CE { Bool quoteMode = False; for (;; cmdLineParams++) { wchar_t c = *cmdLineParams; if (c == L'\"') quoteMode = !quoteMode; else if (c == 0 || (c == L' ' && !quoteMode)) break; } } #endif } { unsigned i; DWORD d; winRes = GetTempPathW(MAX_PATH, path); if (winRes == 0 || winRes > MAX_PATH) return 1; pathLen = wcslen(path); d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); for (i = 0;; i++, d += GetTickCount()) { if (i >= 100) { res = SZ_ERROR_FAIL; break; } wcscpy(path + pathLen, L"7z"); { wchar_t *s = path + wcslen(path); UInt32 value = d; unsigned k; for (k = 0; k < 8; k++) { unsigned t = value & 0xF; value >>= 4; s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; } if (DoesFileOrDirExist(path)) continue; if (CreateDirectoryW(path, NULL)) { wcscat(path, WSTRING_PATH_SEPARATOR); pathLen = wcslen(path); break; } if (GetLastError() != ERROR_ALREADY_EXISTS) { res = SZ_ERROR_FAIL; break; } } #ifndef UNDER_CE wcscpy(workCurDir, path); #endif if (res != SZ_OK) errorMessage = "Can't create temp folder"; } if (res != SZ_OK) { if (!errorMessage) errorMessage = "Error"; PrintErrorMessage(errorMessage); return 1; } if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) { errorMessage = "can not open input file"; res = SZ_ERROR_FAIL; } else { UInt64 pos = 0; if (!FindSignature(&archiveStream.file, &pos)) res = SZ_ERROR_FAIL; else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) res = SZ_ERROR_FAIL; if (res != 0) errorMessage = "Can't find 7z archive"; } if (res == SZ_OK) { lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); } SzArEx_Init(&db); if (res == SZ_OK) { res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); } if (res == SZ_OK) { UInt32 executeFileIndex = (UInt32)(Int32)-1; UInt32 minPrice = 1 << 30; UInt32 i; 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) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; WCHAR *temp; if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH) { res = SZ_ERROR_FAIL; break; } temp = path + pathLen; SzArEx_GetFileNameUtf16(&db, i, temp); { res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } { CSzFile outFile; size_t processedSize; size_t j; size_t nameStartPos = 0; for (j = 0; temp[j] != 0; j++) { if (temp[j] == '/') { temp[j] = 0; MyCreateDir(path); temp[j] = CHAR_PATH_SEPARATOR; nameStartPos = j + 1; } } if (SzArEx_IsDir(&db, i)) { MyCreateDir(path); continue; } else { unsigned extLen; const WCHAR *name = temp + nameStartPos; unsigned len = (unsigned)wcslen(name); unsigned nameLen = FindExt(temp + nameStartPos, &extLen); unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); if (minPrice > price) { minPrice = price; executeFileIndex = i; useShellExecute = (extPrice != k_EXE_ExtIndex); } if (DoesFileOrDirExist(path)) { errorMessage = "Duplicate file"; res = SZ_ERROR_FAIL; break; } if (OutFile_OpenW(&outFile, path)) { errorMessage = "Can't open output file"; res = SZ_ERROR_FAIL; break; } } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { errorMessage = "Can't write output file"; res = SZ_ERROR_FAIL; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.MTime, i)) { const CNtfsFileTime *t = db.MTime.Vals + i; FILETIME mTime; mTime.dwLowDateTime = t->Low; mTime.dwHighDateTime = t->High; SetFileTime(outFile.handle, NULL, NULL, &mTime); } #endif { SRes res2 = File_Close(&outFile); if (res != SZ_OK) break; if (res2 != SZ_OK) { res = res2; break; } } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) SetFileAttributesW(path, db.Attribs.Vals[i]); #endif } } if (res == SZ_OK) { if (executeFileIndex == (UInt32)(Int32)-1) { errorMessage = "There is no file to execute"; res = SZ_ERROR_FAIL; } else { WCHAR *temp = path + pathLen; UInt32 j; SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp); for (j = 0; temp[j] != 0; j++) if (temp[j] == '/') temp[j] = CHAR_PATH_SEPARATOR; } } IAlloc_Free(&allocImp, outBuffer); } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { HANDLE hProcess = 0; #ifndef UNDER_CE WCHAR oldCurDir[MAX_PATH + 2]; oldCurDir[0] = 0; { DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); if (needLen == 0 || needLen > MAX_PATH) oldCurDir[0] = 0; SetCurrentDirectory(workCurDir); } #endif if (useShellExecute) { SHELLEXECUTEINFO ei; UINT32 executeRes; BOOL success; memset(&ei, 0, sizeof(ei)); ei.cbSize = sizeof(ei); ei.lpFile = path; ei.fMask = SEE_MASK_NOCLOSEPROCESS #ifndef UNDER_CE | SEE_MASK_FLAG_DDEWAIT #endif /* | SEE_MASK_NO_CONSOLE */ ; if (wcslen(cmdLineParams) != 0) ei.lpParameters = cmdLineParams; ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */ success = ShellExecuteEx(&ei); executeRes = (UINT32)(UINT_PTR)ei.hInstApp; if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ res = SZ_ERROR_FAIL; else hProcess = ei.hProcess; } else { STARTUPINFOW si; PROCESS_INFORMATION pi; WCHAR cmdLine[MAX_PATH * 3]; wcscpy(cmdLine, path); wcscat(cmdLine, cmdLineParams); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) res = SZ_ERROR_FAIL; else { CloseHandle(pi.hThread); hProcess = pi.hProcess; } } if (hProcess != 0) { WaitForSingleObject(hProcess, INFINITE); if (!GetExitCodeProcess(hProcess, &exitCode)) exitCode = 1; CloseHandle(hProcess); } #ifndef UNDER_CE SetCurrentDirectory(oldCurDir); #endif } path[pathLen] = L'\0'; RemoveDirWithSubItems(path); if (res == SZ_OK) return (int)exitCode; { if (res == SZ_ERROR_UNSUPPORTED) errorMessage = "Decoder doesn't support this archive"; else if (res == SZ_ERROR_MEM) errorMessage = "Can't allocate required memory"; else if (res == SZ_ERROR_CRC) errorMessage = "CRC error"; else { if (!errorMessage) errorMessage = "ERROR"; } if (errorMessage) PrintErrorMessage(errorMessage); } return 1; }