mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-18 15:08:43 +00:00
237 lines
6.4 KiB
C++
237 lines
6.4 KiB
C++
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "nel/misc/types_nl.h"
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "7zCrc.h"
|
||
|
#include "7zIn.h"
|
||
|
#include "7zExtract.h"
|
||
|
|
||
|
typedef struct _CFileInStream
|
||
|
{
|
||
|
ISzInStream InStream;
|
||
|
FILE *File;
|
||
|
} CFileInStream;
|
||
|
|
||
|
#ifdef _LZMA_IN_CB
|
||
|
|
||
|
#define kBufferSize (1 << 12)
|
||
|
Byte g_Buffer[kBufferSize];
|
||
|
|
||
|
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
|
||
|
{
|
||
|
CFileInStream *s = (CFileInStream *)object;
|
||
|
size_t processedSizeLoc;
|
||
|
if (maxRequiredSize > kBufferSize)
|
||
|
maxRequiredSize = kBufferSize;
|
||
|
processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File);
|
||
|
*buffer = g_Buffer;
|
||
|
if (processedSize != 0)
|
||
|
*processedSize = processedSizeLoc;
|
||
|
return SZ_OK;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
|
||
|
{
|
||
|
CFileInStream *s = (CFileInStream *)object;
|
||
|
size_t processedSizeLoc = fread(buffer, 1, size, s->File);
|
||
|
if (processedSize != 0)
|
||
|
*processedSize = processedSizeLoc;
|
||
|
return SZ_OK;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
||
|
{
|
||
|
CFileInStream *s = (CFileInStream *)object;
|
||
|
int res = fseek(s->File, (long)pos, SEEK_SET);
|
||
|
if (res == 0)
|
||
|
return SZ_OK;
|
||
|
return SZE_FAIL;
|
||
|
}
|
||
|
|
||
|
void PrintError(char *sz)
|
||
|
{
|
||
|
printf("\nERROR: %s\n", sz);
|
||
|
}
|
||
|
|
||
|
int main(int numargs, char *args[])
|
||
|
{
|
||
|
CFileInStream archiveStream;
|
||
|
CArchiveDatabaseEx db;
|
||
|
SZ_RESULT res;
|
||
|
ISzAlloc allocImp;
|
||
|
ISzAlloc allocTempImp;
|
||
|
|
||
|
printf("\n7z ANSI-C Decoder 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04\n");
|
||
|
if (numargs == 1)
|
||
|
{
|
||
|
printf(
|
||
|
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
||
|
"<Commands>\n"
|
||
|
" e: Extract files from archive\n"
|
||
|
" l: List contents of archive\n"
|
||
|
" t: Test integrity of archive\n");
|
||
|
return 0;
|
||
|
}
|
||
|
if (numargs < 3)
|
||
|
{
|
||
|
PrintError("incorrect command");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
archiveStream.File = fopen(args[2], "rb");
|
||
|
if (archiveStream.File == 0)
|
||
|
{
|
||
|
PrintError("can not open input file");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
archiveStream.InStream.Read = SzFileReadImp;
|
||
|
archiveStream.InStream.Seek = SzFileSeekImp;
|
||
|
|
||
|
allocImp.Alloc = SzAlloc;
|
||
|
allocImp.Free = SzFree;
|
||
|
|
||
|
allocTempImp.Alloc = SzAllocTemp;
|
||
|
allocTempImp.Free = SzFreeTemp;
|
||
|
|
||
|
InitCrcTable();
|
||
|
SzArDbExInit(&db);
|
||
|
res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
|
||
|
if (res == SZ_OK)
|
||
|
{
|
||
|
char *command = args[1];
|
||
|
int listCommand = 0;
|
||
|
int testCommand = 0;
|
||
|
int extractCommand = 0;
|
||
|
if (strcmp(command, "l") == 0)
|
||
|
listCommand = 1;
|
||
|
if (strcmp(command, "t") == 0)
|
||
|
testCommand = 1;
|
||
|
else if (strcmp(command, "e") == 0)
|
||
|
extractCommand = 1;
|
||
|
|
||
|
if (listCommand)
|
||
|
{
|
||
|
UInt32 i;
|
||
|
for (i = 0; i < db.Database.NumFiles; i++)
|
||
|
{
|
||
|
CFileItem *f = db.Database.Files + i;
|
||
|
printf("%10d %s\n", (int)f->Size, f->Name);
|
||
|
}
|
||
|
}
|
||
|
else if (testCommand || extractCommand)
|
||
|
{
|
||
|
UInt32 i;
|
||
|
|
||
|
/*
|
||
|
if you need cache, use these 3 variables.
|
||
|
if you use external function, you can make these variable as static.
|
||
|
*/
|
||
|
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||
|
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||
|
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||
|
|
||
|
printf("\n");
|
||
|
for (i = 0; i < db.Database.NumFiles; i++)
|
||
|
{
|
||
|
size_t offset;
|
||
|
size_t outSizeProcessed;
|
||
|
CFileItem *f = db.Database.Files + i;
|
||
|
if (f->IsDirectory)
|
||
|
printf("Directory ");
|
||
|
else
|
||
|
printf(testCommand ?
|
||
|
"Testing ":
|
||
|
"Extracting");
|
||
|
printf(" %s", f->Name);
|
||
|
if (f->IsDirectory)
|
||
|
{
|
||
|
printf("\n");
|
||
|
continue;
|
||
|
}
|
||
|
res = SzExtract(&archiveStream.InStream, &db, i,
|
||
|
&blockIndex, &outBuffer, &outBufferSize,
|
||
|
&offset, &outSizeProcessed,
|
||
|
&allocImp, &allocTempImp);
|
||
|
if (res != SZ_OK)
|
||
|
break;
|
||
|
if (!testCommand)
|
||
|
{
|
||
|
FILE *outputHandle;
|
||
|
UInt32 processedSize;
|
||
|
char *fileName = f->Name;
|
||
|
size_t nameLen = strlen(f->Name);
|
||
|
for (; nameLen > 0; nameLen--)
|
||
|
if (f->Name[nameLen - 1] == '/')
|
||
|
{
|
||
|
fileName = f->Name + nameLen;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
outputHandle = fopen(fileName, "wb+");
|
||
|
if (outputHandle == 0)
|
||
|
{
|
||
|
PrintError("can not open output file");
|
||
|
res = SZE_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle);
|
||
|
if (processedSize != outSizeProcessed)
|
||
|
{
|
||
|
PrintError("can not write output file");
|
||
|
res = SZE_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
if (fclose(outputHandle))
|
||
|
{
|
||
|
PrintError("can not close output file");
|
||
|
res = SZE_FAIL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
allocImp.Free(outBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PrintError("incorrect command");
|
||
|
res = SZE_FAIL;
|
||
|
}
|
||
|
}
|
||
|
SzArDbExFree(&db, allocImp.Free);
|
||
|
|
||
|
fclose(archiveStream.File);
|
||
|
if (res == SZ_OK)
|
||
|
{
|
||
|
printf("\nEverything is Ok\n");
|
||
|
return 0;
|
||
|
}
|
||
|
if (res == SZE_OUTOFMEMORY)
|
||
|
PrintError("can not allocate memory");
|
||
|
else
|
||
|
printf("\nERROR #%d\n", res);
|
||
|
return 1;
|
||
|
}
|