int Unseven(const char *filename, STRING **list) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; UInt16 *temp = NULL; size_t tempSize = 0; Bool do_save = (globaldata.gd_inidata->archive_dir && *(globaldata.gd_inidata->archive_dir))? False : True; char *subdir = NULL; // UInt32 parents[NUM_PARENTS_MAX]; // printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); if (!filename || !*filename) return -1; // error #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, filename)) #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) { 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); 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); /* { // progression output static char s[256]; snprintf(s, 255, _("Extracting (%d%%)"), ((i + 1) * 100) / db.NumFiles); HandleSemaphoreText(s, list, !i ? 1 : 0); }*/ if (isDir) ;//printf("/"); else { res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } // write data to disk { CSzFile outFile; size_t processedSize; size_t j; UInt16 *name = (UInt16 *)temp; const UInt16 *destPath = (const UInt16 *)name; WRes wres; for (j = 0; name[j] != 0; j++) if (name[j] == '/') { name[j] = 0; MyCreateDir(name, &subdir, &do_save); name[j] = CHAR_PATH_SEPARATOR; } if (isDir) { MyCreateDir(destPath, &subdir, &do_save); //printf("\n"); continue; } if (do_save == False) continue; wres = OutFile_OpenUtf16(&outFile, destPath, &subdir, &do_save); if (wres == -1) continue; if (wres) { 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("<br />ERROR #%d\n", res); return -1; }
ArchiveFile* SzArchive::OpenFile(const char* name) { u16 fname[512]; for (int i = 0; i < szarchive.NumFiles; i++) { unsigned isDir = SzArEx_IsDir(&szarchive, i); if (isDir) continue; int len = SzArEx_GetFileNameUtf16(&szarchive, i, fname); char szname[512]; int j = 0; for (; j < len && j < sizeof(szname) - 1; j++) szname[j] = fname[j]; szname[j] = 0; if (strcmp(name, szname)) continue; size_t offset = 0; size_t out_size_processed = 0; SRes res = SzArEx_Extract(&szarchive, &lookStream.vt, i, &block_idx, &out_buffer, &out_buffer_size, &offset, &out_size_processed, &g_Alloc, &g_Alloc); if (res != SZ_OK) return NULL; return new SzArchiveFile(out_buffer, offset, (u32)out_size_processed); } return NULL; }
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; }
bool F7ZFile::Open(bool quiet) { Archive = new C7zArchive(Reader); int skipped = 0; SRes res; res = Archive->Open(); if (res != SZ_OK) { delete Archive; Archive = NULL; if (!quiet) { Printf("\n" TEXTCOLOR_RED "%s: ", Filename); if (res == SZ_ERROR_UNSUPPORTED) { Printf("Decoder does not support this archive\n"); } else if (res == SZ_ERROR_MEM) { Printf("Cannot allocate memory\n"); } else if (res == SZ_ERROR_CRC) { Printf("CRC error\n"); } else { Printf("error #%d\n", res); } } return false; } CSzArEx* const archPtr = &Archive->DB; NumLumps = archPtr->NumFiles; Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; TArray<UInt16> nameUTF16; TArray<char> nameASCII; for (uint32_t i = 0; i < NumLumps; ++i) { // skip Directories if (SzArEx_IsDir(archPtr, i)) { skipped++; continue; } const size_t nameLength = SzArEx_GetFileNameUtf16(archPtr, i, NULL); if (0 == nameLength) { ++skipped; continue; } nameUTF16.Resize((unsigned)nameLength); nameASCII.Resize((unsigned)nameLength); SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]); for (size_t c = 0; c < nameLength; ++c) { nameASCII[c] = static_cast<char>(nameUTF16[c]); } FixPathSeperator(&nameASCII[0]); FString name = &nameASCII[0]; name.ToLower(); lump_p->LumpNameSetup(name); lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i)); lump_p->Owner = this; lump_p->Flags = LUMPF_ZIPFILE; lump_p->Position = i; lump_p->CheckEmbedded(); lump_p++; } // Resize the lump record array to its actual size NumLumps -= skipped; if (NumLumps > 0) { // Quick check for unsupported compression method TArray<char> temp; temp.Resize(Lumps[0].LumpSize); if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) { if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename); return false; } } if (!quiet && !batchrun) Printf(", %d lumps\n", NumLumps); PostProcessArchive(&Lumps[0], sizeof(F7ZLump)); return true; }
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; }
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; }
struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode) { UNUSED(mode); // TODO: support truncating, appending and creating, and write struct VDir7z* vd7z = (struct VDir7z*) vd; if ((mode & O_RDWR) == O_RDWR) { // Read/Write support is not yet implemented. return 0; } if (mode & O_WRONLY) { // Write support is not yet implemented. return 0; } size_t pathLength = strlen(path); UInt32 i; for (i = 0; i < vd7z->db.NumFiles; ++i) { if (SzArEx_IsDir(&vd7z->db, i)) { continue; } size_t nameLength = SzArEx_GetFileNameUtf16(&vd7z->db, i, 0) * sizeof(UInt16); UInt16* name = malloc(nameLength); SzArEx_GetFileNameUtf16(&vd7z->db, i, name); if (utfcmp(name, path, nameLength - sizeof(UInt16), pathLength) == 0) { free(name); break; } free(name); } if (i == vd7z->db.NumFiles) { return 0; // No file found } struct VFile7z* vf = malloc(sizeof(struct VFile7z)); vf->vd = vd7z; size_t outBufferSize; UInt32 blockIndex; vf->outBuffer = 0; SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.s, i, &blockIndex, &vf->outBuffer, &outBufferSize, &vf->bufferOffset, &vf->size, &vd7z->allocImp, &vd7z->allocTempImp); if (res != SZ_OK) { free(vf); return 0; } vf->d.close = _vf7zClose; vf->d.seek = _vf7zSeek; vf->d.read = _vf7zRead; vf->d.readline = VFileReadline; vf->d.write = _vf7zWrite; vf->d.map = _vf7zMap; vf->d.unmap = _vf7zUnmap; vf->d.truncate = _vf7zTruncate; vf->d.size = _vf7zSize; return &vf->d; }