123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- #include "7Zitf.h"
- #include "Precomp.h"
- #include <stdio.h>
- #include <string.h>
- #include "CpuArch.h"
- #include "7z.h"
- #include "7zAlloc.h"
- #include "7zBuf.h"
- #include "7zCrc.h"
- #include "7zFile.h"
- #include "7zVersion.h"
- #ifndef USE_WINDOWS_FILE
- /* for mkdir */
- #ifdef _WIN32
- #include <direct.h>
- #else
- #include <sys/stat.h>
- #include <errno.h>
- #endif
- #endif
- extern "C"
- {
- #define kInputBufSize ((size_t)1 << 18)
- static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
- static void Print(const char *s)
- {
- fputs(s, stdout);
- }
- static int Buf_EnsureSize(CBuf *dest, size_t size)
- {
- if (dest->size >= size)
- return 1;
- Buf_Free(dest, &g_Alloc);
- return Buf_Create(dest, size, &g_Alloc);
- }
- static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
- #ifndef _USE_UTF8
- , UINT codePage
- #endif
- )
- {
- unsigned len = 0;
- for (len = 0; s[len] != 0; len++);
- #ifndef _USE_UTF8
- {
- unsigned size = len * 3 + 100;
- if (!Buf_EnsureSize(buf, size))
- return SZ_ERROR_MEM;
- {
- buf->data[0] = 0;
- if (len != 0)
- {
- char defaultChar = '_';
- BOOL defUsed;
- unsigned numChars = 0;
- numChars = WideCharToMultiByte(codePage, 0, (LPCWSTR)s, len, (char *)buf->data, size, &defaultChar, &defUsed);
- if (numChars == 0 || numChars >= size)
- return SZ_ERROR_FAIL;
- buf->data[numChars] = 0;
- }
- return SZ_OK;
- }
- }
- #else
- return Utf16_To_Utf8Buf(buf, s, len);
- #endif
- }
- #ifdef _WIN32
- #ifndef USE_WINDOWS_FILE
- static UINT g_FileCodePage = CP_ACP;
- #endif
- #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage
- #else
- #define MY_FILE_CODE_PAGE_PARAM
- #endif
- static WRes MyCreateDir(const UInt16 *name)
- {
- #ifdef USE_WINDOWS_FILE
- return CreateDirectoryW((LPCWSTR)name, NULL) ? 0 : GetLastError();
- #else
- CBuf buf;
- WRes res;
- Buf_Init(&buf);
- RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));
- res =
- #ifdef _WIN32
- _mkdir((const char *)buf.data)
- #else
- mkdir((const char *)buf.data, 0777)
- #endif
- == 0 ? 0 : errno;
- Buf_Free(&buf, &g_Alloc);
- return res;
- #endif
- }
- static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
- {
- #ifdef USE_WINDOWS_FILE
- return OutFile_OpenW(p, (LPCWSTR)name);
- #else
- CBuf buf;
- WRes res;
- Buf_Init(&buf);
- RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));
- res = OutFile_Open(p, (const char *)buf.data);
- Buf_Free(&buf, &g_Alloc);
- return res;
- #endif
- }
- static SRes PrintString(const UInt16 *s)
- {
- CBuf buf;
- SRes res;
- Buf_Init(&buf);
- res = Utf16_To_Char(&buf, s
- #ifndef _USE_UTF8
- , CP_OEMCP
- #endif
- );
- if (res == SZ_OK)
- Print((const char *)buf.data);
- Buf_Free(&buf, &g_Alloc);
- return res;
- }
- static void UInt64ToStr(UInt64 value, char *s, int numDigits)
- {
- char temp[32];
- int pos = 0;
- do
- {
- temp[pos++] = (char)('0' + (unsigned)(value % 10));
- value /= 10;
- } while (value != 0);
- for (numDigits -= pos; numDigits > 0; numDigits--)
- *s++ = ' ';
- do
- *s++ = temp[--pos];
- while (pos);
- *s = '\0';
- }
- #define PERIOD_4 (4 * 365 + 1)
- #define PERIOD_100 (PERIOD_4 * 25 - 1)
- #define PERIOD_400 (PERIOD_100 * 4 + 1)
- static void PrintLF()
- {
- Print("\n");
- }
- static void PrintError(const char *s)
- {
- Print("\nERROR: ");
- Print(s);
- PrintLF();
- }
- bool Decompress(const char * file)
- {
- ISzAlloc allocImp;
- ISzAlloc allocTempImp;
- CFileInStream archiveStream;
- CLookToRead2 lookStream;
- CSzArEx db;
- SRes res;
- UInt16 *temp = NULL;
- size_t tempSize = 0;
- allocImp = g_Alloc;
- allocTempImp = g_Alloc;
- if (InFile_Open(&archiveStream.file, file))
- {
- 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)
- {
-
- int fullPaths = 1;
-
- 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 (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);
- 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;
- }
- {
- 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);
- return res == SZ_OK;
- }
- }
|