tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LzmaUtil.c (6556B)


      1 /* LzmaUtil.c -- Test application for LZMA compression
      2 2017-04-27 : Igor Pavlov : Public domain */
      3 
      4 #include "../../Precomp.h"
      5 
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include "../../CpuArch.h"
     11 
     12 #include "../../Alloc.h"
     13 #include "../../7zFile.h"
     14 #include "../../7zVersion.h"
     15 #include "../../LzmaDec.h"
     16 #include "../../LzmaEnc.h"
     17 
     18 static const char * const kCantReadMessage = "Can not read input file";
     19 static const char * const kCantWriteMessage = "Can not write output file";
     20 static const char * const kCantAllocateMessage = "Can not allocate memory";
     21 static const char * const kDataErrorMessage = "Data error";
     22 
     23 static void PrintHelp(char *buffer)
     24 {
     25  strcat(buffer,
     26    "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
     27    "Usage:  lzma <e|d> inputFile outputFile\n"
     28    "  e: encode file\n"
     29    "  d: decode file\n");
     30 }
     31 
     32 static int PrintError(char *buffer, const char *message)
     33 {
     34  strcat(buffer, "\nError: ");
     35  strcat(buffer, message);
     36  strcat(buffer, "\n");
     37  return 1;
     38 }
     39 
     40 static int PrintErrorNumber(char *buffer, SRes val)
     41 {
     42  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
     43  return 1;
     44 }
     45 
     46 static int PrintUserError(char *buffer)
     47 {
     48  return PrintError(buffer, "Incorrect command");
     49 }
     50 
     51 
     52 #define IN_BUF_SIZE (1 << 16)
     53 #define OUT_BUF_SIZE (1 << 16)
     54 
     55 
     56 static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
     57    UInt64 unpackSize)
     58 {
     59  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
     60  Byte inBuf[IN_BUF_SIZE];
     61  Byte outBuf[OUT_BUF_SIZE];
     62  size_t inPos = 0, inSize = 0, outPos = 0;
     63  LzmaDec_Init(state);
     64  for (;;)
     65  {
     66    if (inPos == inSize)
     67    {
     68      inSize = IN_BUF_SIZE;
     69      RINOK(inStream->Read(inStream, inBuf, &inSize));
     70      inPos = 0;
     71    }
     72    {
     73      SRes res;
     74      SizeT inProcessed = inSize - inPos;
     75      SizeT outProcessed = OUT_BUF_SIZE - outPos;
     76      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
     77      ELzmaStatus status;
     78      if (thereIsSize && outProcessed > unpackSize)
     79      {
     80        outProcessed = (SizeT)unpackSize;
     81        finishMode = LZMA_FINISH_END;
     82      }
     83      
     84      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
     85        inBuf + inPos, &inProcessed, finishMode, &status);
     86      inPos += inProcessed;
     87      outPos += outProcessed;
     88      unpackSize -= outProcessed;
     89      
     90      if (outStream)
     91        if (outStream->Write(outStream, outBuf, outPos) != outPos)
     92          return SZ_ERROR_WRITE;
     93        
     94      outPos = 0;
     95      
     96      if (res != SZ_OK || (thereIsSize && unpackSize == 0))
     97        return res;
     98      
     99      if (inProcessed == 0 && outProcessed == 0)
    100      {
    101        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
    102          return SZ_ERROR_DATA;
    103        return res;
    104      }
    105    }
    106  }
    107 }
    108 
    109 
    110 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
    111 {
    112  UInt64 unpackSize;
    113  int i;
    114  SRes res = 0;
    115 
    116  CLzmaDec state;
    117 
    118  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
    119  unsigned char header[LZMA_PROPS_SIZE + 8];
    120 
    121  /* Read and parse header */
    122 
    123  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
    124 
    125  unpackSize = 0;
    126  for (i = 0; i < 8; i++)
    127    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
    128 
    129  LzmaDec_Construct(&state);
    130  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
    131  res = Decode2(&state, outStream, inStream, unpackSize);
    132  LzmaDec_Free(&state, &g_Alloc);
    133  return res;
    134 }
    135 
    136 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
    137 {
    138  CLzmaEncHandle enc;
    139  SRes res;
    140  CLzmaEncProps props;
    141 
    142  UNUSED_VAR(rs);
    143 
    144  enc = LzmaEnc_Create(&g_Alloc);
    145  if (enc == 0)
    146    return SZ_ERROR_MEM;
    147 
    148  LzmaEncProps_Init(&props);
    149  res = LzmaEnc_SetProps(enc, &props);
    150 
    151  if (res == SZ_OK)
    152  {
    153    Byte header[LZMA_PROPS_SIZE + 8];
    154    size_t headerSize = LZMA_PROPS_SIZE;
    155    int i;
    156 
    157    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
    158    for (i = 0; i < 8; i++)
    159      header[headerSize++] = (Byte)(fileSize >> (8 * i));
    160    if (outStream->Write(outStream, header, headerSize) != headerSize)
    161      res = SZ_ERROR_WRITE;
    162    else
    163    {
    164      if (res == SZ_OK)
    165        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
    166    }
    167  }
    168  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
    169  return res;
    170 }
    171 
    172 
    173 static int main2(int numArgs, const char *args[], char *rs)
    174 {
    175  CFileSeqInStream inStream;
    176  CFileOutStream outStream;
    177  char c;
    178  int res;
    179  int encodeMode;
    180  Bool useOutFile = False;
    181 
    182  FileSeqInStream_CreateVTable(&inStream);
    183  File_Construct(&inStream.file);
    184 
    185  FileOutStream_CreateVTable(&outStream);
    186  File_Construct(&outStream.file);
    187 
    188  if (numArgs == 1)
    189  {
    190    PrintHelp(rs);
    191    return 0;
    192  }
    193 
    194  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
    195    return PrintUserError(rs);
    196 
    197  c = args[1][0];
    198  encodeMode = (c == 'e' || c == 'E');
    199  if (!encodeMode && c != 'd' && c != 'D')
    200    return PrintUserError(rs);
    201 
    202  {
    203    size_t t4 = sizeof(UInt32);
    204    size_t t8 = sizeof(UInt64);
    205    if (t4 != 4 || t8 != 8)
    206      return PrintError(rs, "Incorrect UInt32 or UInt64");
    207  }
    208 
    209  if (InFile_Open(&inStream.file, args[2]) != 0)
    210    return PrintError(rs, "Can not open input file");
    211 
    212  if (numArgs > 3)
    213  {
    214    useOutFile = True;
    215    if (OutFile_Open(&outStream.file, args[3]) != 0)
    216      return PrintError(rs, "Can not open output file");
    217  }
    218  else if (encodeMode)
    219    PrintUserError(rs);
    220 
    221  if (encodeMode)
    222  {
    223    UInt64 fileSize;
    224    File_GetLength(&inStream.file, &fileSize);
    225    res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
    226  }
    227  else
    228  {
    229    res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
    230  }
    231 
    232  if (useOutFile)
    233    File_Close(&outStream.file);
    234  File_Close(&inStream.file);
    235 
    236  if (res != SZ_OK)
    237  {
    238    if (res == SZ_ERROR_MEM)
    239      return PrintError(rs, kCantAllocateMessage);
    240    else if (res == SZ_ERROR_DATA)
    241      return PrintError(rs, kDataErrorMessage);
    242    else if (res == SZ_ERROR_WRITE)
    243      return PrintError(rs, kCantWriteMessage);
    244    else if (res == SZ_ERROR_READ)
    245      return PrintError(rs, kCantReadMessage);
    246    return PrintErrorNumber(rs, res);
    247  }
    248  return 0;
    249 }
    250 
    251 
    252 int MY_CDECL main(int numArgs, const char *args[])
    253 {
    254  char rs[800] = { 0 };
    255  int res = main2(numArgs, args, rs);
    256  fputs(rs, stdout);
    257  return res;
    258 }