259 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			259 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* LzmaUtil.c -- Test application for LZMA compression
							 | 
						||
| 
								 | 
							
								2017-04-27 : Igor Pavlov : Public domain */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "Precomp.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "CpuArch.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "Alloc.h"
							 | 
						||
| 
								 | 
							
								#include "7zFile.h"
							 | 
						||
| 
								 | 
							
								#include "7zVersion.h"
							 | 
						||
| 
								 | 
							
								#include "LzmaDec.h"
							 | 
						||
| 
								 | 
							
								#include "LzmaEnc.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const char * const kCantReadMessage = "Can not read input file";
							 | 
						||
| 
								 | 
							
								static const char * const kCantWriteMessage = "Can not write output file";
							 | 
						||
| 
								 | 
							
								static const char * const kCantAllocateMessage = "Can not allocate memory";
							 | 
						||
| 
								 | 
							
								static const char * const kDataErrorMessage = "Data error";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void PrintHelp(char *buffer)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  strcat(buffer,
							 | 
						||
| 
								 | 
							
								    "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
							 | 
						||
| 
								 | 
							
								    "Usage:  lzma <e|d> inputFile outputFile\n"
							 | 
						||
| 
								 | 
							
								    "  e: encode file\n"
							 | 
						||
| 
								 | 
							
								    "  d: decode file\n");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int PrintError(char *buffer, const char *message)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  strcat(buffer, "\nError: ");
							 | 
						||
| 
								 | 
							
								  strcat(buffer, message);
							 | 
						||
| 
								 | 
							
								  strcat(buffer, "\n");
							 | 
						||
| 
								 | 
							
								  return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int PrintErrorNumber(char *buffer, SRes val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
							 | 
						||
| 
								 | 
							
								  return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int PrintUserError(char *buffer)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return PrintError(buffer, "Incorrect command");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define IN_BUF_SIZE  (1 << 14)//(1 << 16)
							 | 
						||
| 
								 | 
							
								#define OUT_BUF_SIZE (1 << 14)//(1 << 16)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
							 | 
						||
| 
								 | 
							
								    UInt64 unpackSize)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
							 | 
						||
| 
								 | 
							
								  Byte inBuf[IN_BUF_SIZE];
							 | 
						||
| 
								 | 
							
								  Byte outBuf[OUT_BUF_SIZE];
							 | 
						||
| 
								 | 
							
								  size_t inPos = 0, inSize = 0, outPos = 0;
							 | 
						||
| 
								 | 
							
								  LzmaDec_Init(state);
							 | 
						||
| 
								 | 
							
								  for (;;)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if (inPos == inSize)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      inSize = IN_BUF_SIZE;
							 | 
						||
| 
								 | 
							
								      RINOK(inStream->Read(inStream, inBuf, &inSize));
							 | 
						||
| 
								 | 
							
								      inPos = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      SRes res;
							 | 
						||
| 
								 | 
							
								      SizeT inProcessed = inSize - inPos;
							 | 
						||
| 
								 | 
							
								      SizeT outProcessed = OUT_BUF_SIZE - outPos;
							 | 
						||
| 
								 | 
							
								      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
							 | 
						||
| 
								 | 
							
								      ELzmaStatus status;
							 | 
						||
| 
								 | 
							
								      if (thereIsSize && outProcessed > unpackSize)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        outProcessed = (SizeT)unpackSize;
							 | 
						||
| 
								 | 
							
								        finishMode = LZMA_FINISH_END;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
							 | 
						||
| 
								 | 
							
								        inBuf + inPos, &inProcessed, finishMode, &status);
							 | 
						||
| 
								 | 
							
								      inPos += inProcessed;
							 | 
						||
| 
								 | 
							
								      outPos += outProcessed;
							 | 
						||
| 
								 | 
							
								      unpackSize -= outProcessed;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      if (outStream)
							 | 
						||
| 
								 | 
							
								        if (outStream->Write(outStream, outBuf, outPos) != outPos)
							 | 
						||
| 
								 | 
							
								          return SZ_ERROR_WRITE;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								      outPos = 0;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      if (res != SZ_OK || (thereIsSize && unpackSize == 0))
							 | 
						||
| 
								 | 
							
								        return res;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      if (inProcessed == 0 && outProcessed == 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
							 | 
						||
| 
								 | 
							
								          return SZ_ERROR_DATA;
							 | 
						||
| 
								 | 
							
								        return res;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  UInt64 unpackSize;
							 | 
						||
| 
								 | 
							
								  int i;
							 | 
						||
| 
								 | 
							
								  SRes res = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  CLzmaDec state;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
							 | 
						||
| 
								 | 
							
								  unsigned char header[LZMA_PROPS_SIZE + 8];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Read and parse header */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  unpackSize = 0;
							 | 
						||
| 
								 | 
							
								  for (i = 0; i < 8; i++)
							 | 
						||
| 
								 | 
							
								    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  LzmaDec_Construct(&state);
							 | 
						||
| 
								 | 
							
								  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
							 | 
						||
| 
								 | 
							
								  res = Decode2(&state, outStream, inStream, unpackSize);
							 | 
						||
| 
								 | 
							
								  LzmaDec_Free(&state, &g_Alloc);
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  CLzmaEncHandle enc;
							 | 
						||
| 
								 | 
							
								  SRes res;
							 | 
						||
| 
								 | 
							
								  CLzmaEncProps props;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  UNUSED_VAR(rs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  enc = LzmaEnc_Create(&g_Alloc);
							 | 
						||
| 
								 | 
							
								  if (enc == 0)
							 | 
						||
| 
								 | 
							
								    return SZ_ERROR_MEM;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  LzmaEncProps_Init(&props);
							 | 
						||
| 
								 | 
							
								  res = LzmaEnc_SetProps(enc, &props);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (res == SZ_OK)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    Byte header[LZMA_PROPS_SIZE + 8];
							 | 
						||
| 
								 | 
							
								    size_t headerSize = LZMA_PROPS_SIZE;
							 | 
						||
| 
								 | 
							
								    int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
							 | 
						||
| 
								 | 
							
								    for (i = 0; i < 8; i++)
							 | 
						||
| 
								 | 
							
								      header[headerSize++] = (Byte)(fileSize >> (8 * i));
							 | 
						||
| 
								 | 
							
								    if (outStream->Write(outStream, header, headerSize) != headerSize)
							 | 
						||
| 
								 | 
							
								      res = SZ_ERROR_WRITE;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (res == SZ_OK)
							 | 
						||
| 
								 | 
							
								        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int main2(int numArgs, const char *args[], char *rs)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  CFileSeqInStream inStream;
							 | 
						||
| 
								 | 
							
								  CFileOutStream outStream;
							 | 
						||
| 
								 | 
							
								  char c;
							 | 
						||
| 
								 | 
							
								  int res;
							 | 
						||
| 
								 | 
							
								  int encodeMode;
							 | 
						||
| 
								 | 
							
								  Bool useOutFile = False;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  FileSeqInStream_CreateVTable(&inStream);
							 | 
						||
| 
								 | 
							
								  File_Construct(&inStream.file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  FileOutStream_CreateVTable(&outStream);
							 | 
						||
| 
								 | 
							
								  File_Construct(&outStream.file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (numArgs == 1)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    PrintHelp(rs);
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
							 | 
						||
| 
								 | 
							
								    return PrintUserError(rs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  c = args[1][0];
							 | 
						||
| 
								 | 
							
								  encodeMode = (c == 'e' || c == 'E');
							 | 
						||
| 
								 | 
							
								  if (!encodeMode && c != 'd' && c != 'D')
							 | 
						||
| 
								 | 
							
								    return PrintUserError(rs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    size_t t4 = sizeof(UInt32);
							 | 
						||
| 
								 | 
							
								    size_t t8 = sizeof(UInt64);
							 | 
						||
| 
								 | 
							
								    if (t4 != 4 || t8 != 8)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, "Incorrect UInt32 or UInt64");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (InFile_Open(&inStream.file, args[2]) != 0)
							 | 
						||
| 
								 | 
							
								    return PrintError(rs, "Can not open input file");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (numArgs > 3)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    useOutFile = True;
							 | 
						||
| 
								 | 
							
								    if (OutFile_Open(&outStream.file, args[3]) != 0)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, "Can not open output file");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (encodeMode)
							 | 
						||
| 
								 | 
							
								    PrintUserError(rs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (encodeMode)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    UInt64 fileSize;
							 | 
						||
| 
								 | 
							
								    File_GetLength(&inStream.file, &fileSize);
							 | 
						||
| 
								 | 
							
								    res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (useOutFile)
							 | 
						||
| 
								 | 
							
								    File_Close(&outStream.file);
							 | 
						||
| 
								 | 
							
								  File_Close(&inStream.file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (res != SZ_OK)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if (res == SZ_ERROR_MEM)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, kCantAllocateMessage);
							 | 
						||
| 
								 | 
							
								    else if (res == SZ_ERROR_DATA)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, kDataErrorMessage);
							 | 
						||
| 
								 | 
							
								    else if (res == SZ_ERROR_WRITE)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, kCantWriteMessage);
							 | 
						||
| 
								 | 
							
								    else if (res == SZ_ERROR_READ)
							 | 
						||
| 
								 | 
							
								      return PrintError(rs, kCantReadMessage);
							 | 
						||
| 
								 | 
							
								    return PrintErrorNumber(rs, res);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int MY_CDECL main(int numArgs, const char *args[])
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  char rs[800] = { 0 };
							 | 
						||
| 
								 | 
							
								  int res = main2(numArgs, args, rs);
							 | 
						||
| 
								 | 
							
								  fputs(rs, stdout);
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								}
							 |