summaryrefslogtreecommitdiffstats
path: root/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp')
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp799
1 files changed, 799 insertions, 0 deletions
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
new file mode 100644
index 0000000000..f27333741f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -0,0 +1,799 @@
+// LzmaAlone.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "../../../../C/CpuArch.h"
+
+#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)
+#include <fcntl.h>
+#include <io.h>
+#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)
+#else
+#define MY_SET_BINARY_MODE(file)
+#endif
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../../C/7zVersion.h"
+#include "../../../../C/Alloc.h"
+#include "../../../../C/Lzma86.h"
+
+#include "../../../Windows/NtCheck.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/System.h"
+#endif
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/LzmaDecoder.h"
+#include "../../Compress/LzmaEncoder.h"
+
+#include "../../UI/Console/BenchCon.h"
+#include "../../UI/Console/ConsoleClose.h"
+
+bool g_LargePagesMode = false;
+
+using namespace NCommandLineParser;
+
+static const unsigned kDictSizeLog = 24;
+
+#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
+
+static const char * const kHelpString =
+ "Usage: lzma <command> [inputFile] [outputFile] [<switches>...]\n"
+ "\n"
+ "<command>\n"
+ " e : Encode file\n"
+ " d : Decode file\n"
+ " b : Benchmark\n"
+ "<switches>\n"
+ " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n"
+ " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"
+ " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"
+ " -mc{N} : set number of cycles for match finder\n"
+ " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"
+ " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"
+ " -pb{N} : set number of pos bits : [0, 4] : default = 2\n"
+ " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"
+ " -mt{N} : set number of CPU threads\n"
+ " -eos : write end of stream marker\n"
+ " -si : read data from stdin\n"
+ " -so : write data to stdout\n";
+
+
+static const char * const kCantAllocate = "Can not allocate memory";
+static const char * const kReadError = "Read error";
+static const char * const kWriteError = "Write error";
+
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kMethod,
+ kLevel,
+ kAlgo,
+ kDict,
+ kFb,
+ kMc,
+ kLc,
+ kLp,
+ kPb,
+ kMatchFinder,
+ kMultiThread,
+ kEOS,
+ kStdIn,
+ kStdOut,
+ kFilter86
+};
+}
+
+static const CSwitchForm kSwitchForms[] =
+{
+ { "?", NSwitchType::kSimple, false },
+ { "H", NSwitchType::kSimple, false },
+ { "MM", NSwitchType::kString, false, 1 },
+ { "X", NSwitchType::kString, false, 1 },
+ { "A", NSwitchType::kString, false, 1 },
+ { "D", NSwitchType::kString, false, 1 },
+ { "FB", NSwitchType::kString, false, 1 },
+ { "MC", NSwitchType::kString, false, 1 },
+ { "LC", NSwitchType::kString, false, 1 },
+ { "LP", NSwitchType::kString, false, 1 },
+ { "PB", NSwitchType::kString, false, 1 },
+ { "MF", NSwitchType::kString, false, 1 },
+ { "MT", NSwitchType::kString, false, 0 },
+ { "EOS", NSwitchType::kSimple, false },
+ { "SI", NSwitchType::kSimple, false },
+ { "SO", NSwitchType::kSimple, false },
+ { "F86", NSwitchType::kChar, false, 0, "+" }
+};
+
+
+static void Convert_UString_to_AString(const UString &s, AString &temp)
+{
+ int codePage = CP_OEMCP;
+ /*
+ int g_CodePage = -1;
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ */
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
+}
+
+static void PrintErr(const char *s)
+{
+ fputs(s, stderr);
+}
+
+static void PrintErr_LF(const char *s)
+{
+ PrintErr(s);
+ fputc('\n', stderr);
+}
+
+
+static void PrintError(const char *s)
+{
+ PrintErr("\nERROR: ");
+ PrintErr_LF(s);
+}
+
+static void PrintError2(const char *s1, const UString &s2)
+{
+ PrintError(s1);
+ AString a;
+ Convert_UString_to_AString(s2, a);
+ PrintErr_LF(a);
+}
+
+static void PrintError_int(const char *s, int code)
+{
+ PrintError(s);
+ char temp[32];
+ ConvertInt64ToString(code, temp);
+ PrintErr("Error code = ");
+ PrintErr_LF(temp);
+}
+
+
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void Print_UInt64(UInt64 v)
+{
+ char temp[32];
+ ConvertUInt64ToString(v, temp);
+ Print(temp);
+}
+
+static void Print_MB(UInt64 v)
+{
+ Print_UInt64(v);
+ Print(" MiB");
+}
+
+static void Print_Size(const char *s, UInt64 v)
+{
+ Print(s);
+ Print_UInt64(v);
+ Print(" (");
+ Print_MB(v >> 20);
+ Print(")\n");
+}
+
+static void PrintTitle()
+{
+ Print(kCopyrightString);
+}
+
+static void PrintHelp()
+{
+ PrintTitle();
+ Print(kHelpString);
+}
+
+class CProgressPrint:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ UInt64 _size1;
+ UInt64 _size2;
+public:
+ CProgressPrint(): _size1(0), _size2(0) {}
+
+ void ClosePrint();
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#define BACK_STR \
+"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
+static const char * const kBackSpaces =
+BACK_STR
+" "
+BACK_STR;
+
+
+void CProgressPrint::ClosePrint()
+{
+ Print(kBackSpaces);
+}
+
+STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ if (inSize)
+ {
+ UInt64 v1 = *inSize >> 20;
+ UInt64 v2 = _size2;
+ if (outSize)
+ v2 = *outSize >> 20;
+ if (v1 != _size1 || v2 != _size2)
+ {
+ _size1 = v1;
+ _size2 = v2;
+ ClosePrint();
+ Print_MB(_size1);
+ Print(" -> ");
+ Print_MB(_size2);
+ }
+ }
+ return S_OK;
+}
+
+
+static void IncorrectCommand()
+{
+ throw "Incorrect command";
+}
+
+static UInt32 GetNumber(const wchar_t *s)
+{
+ const wchar_t *end;
+ UInt32 v = ConvertStringToUInt32(s, &end);
+ if (*end != 0)
+ IncorrectCommand();
+ return v;
+}
+
+static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)
+{
+ if (parser[index].ThereIs)
+ res = GetNumber(parser[index].PostStrings[0]);
+}
+
+
+static int Error_HRESULT(const char *s, HRESULT res)
+{
+ if (res == E_ABORT)
+ {
+ Print("\n\nBreak signaled\n");
+ return 255;
+ }
+
+ PrintError(s);
+
+ if (res == E_OUTOFMEMORY)
+ {
+ PrintErr_LF(kCantAllocate);
+ return 8;
+ }
+ if (res == E_INVALIDARG)
+ {
+ PrintErr_LF("Ununsupported parameter");
+ }
+ else
+ {
+ char temp[32];
+ ConvertUInt32ToHex(res, temp);
+ PrintErr("Error code = 0x");
+ PrintErr_LF(temp);
+ }
+ return 1;
+}
+
+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
+
+static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)
+{
+ CProperty &prop = props2.AddNew();
+ prop.Name = name;
+ prop.Value = val;
+}
+
+static int main2(int numArgs, const char *args[])
+{
+ NT_CHECK
+
+ if (numArgs == 1)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ /*
+ bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);
+ if (unsupportedTypes)
+ throw "Unsupported base types. Edit Common/Types.h and recompile";
+ */
+
+ UStringVector commandStrings;
+ for (int i = 1; i < numArgs; i++)
+ commandStrings.Add(MultiByteToUnicodeString(args[i]));
+
+ CParser parser;
+ try
+ {
+ if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
+ {
+ PrintError2(parser.ErrorMessage, parser.ErrorLine);
+ return 1;
+ }
+ }
+ catch(...)
+ {
+ IncorrectCommand();
+ }
+
+ if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ bool stdInMode = parser[NKey::kStdIn].ThereIs;
+ bool stdOutMode = parser[NKey::kStdOut].ThereIs;
+
+ if (!stdOutMode)
+ PrintTitle();
+
+ const UStringVector &params = parser.NonSwitchStrings;
+
+ unsigned paramIndex = 0;
+ if (paramIndex >= params.Size())
+ IncorrectCommand();
+ const UString &command = params[paramIndex++];
+
+ CObjectVector<CProperty> props2;
+ bool dictDefined = false;
+ UInt32 dict = (UInt32)(Int32)-1;
+
+ if (parser[NKey::kDict].ThereIs)
+ {
+ UInt32 dictLog;
+ const UString &s = parser[NKey::kDict].PostStrings[0];
+ dictLog = GetNumber(s);
+ dict = 1 << dictLog;
+ dictDefined = true;
+ AddProp(props2, "d", s);
+ }
+
+ if (parser[NKey::kLevel].ThereIs)
+ {
+ const UString &s = parser[NKey::kLevel].PostStrings[0];
+ /* UInt32 level = */ GetNumber(s);
+ AddProp(props2, "x", s);
+ }
+
+ UString mf ("BT4");
+ if (parser[NKey::kMatchFinder].ThereIs)
+ mf = parser[NKey::kMatchFinder].PostStrings[0];
+
+ UInt32 numThreads = (UInt32)(Int32)-1;
+
+ #ifndef _7ZIP_ST
+
+ if (parser[NKey::kMultiThread].ThereIs)
+ {
+ const UString &s = parser[NKey::kMultiThread].PostStrings[0];
+ if (s.IsEmpty())
+ numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ else
+ numThreads = GetNumber(s);
+ AddProp(props2, "mt", s);
+ }
+
+ #endif
+
+
+ if (parser[NKey::kMethod].ThereIs)
+ {
+ const UString &s = parser[NKey::kMethod].PostStrings[0];
+ if (s.IsEmpty() || s[0] != '=')
+ IncorrectCommand();
+ AddProp(props2, "m", s.Ptr(1));
+ }
+
+ if (StringsAreEqualNoCase_Ascii(command, "b"))
+ {
+ UInt32 numIterations = 1;
+ if (paramIndex < params.Size())
+ numIterations = GetNumber(params[paramIndex++]);
+ if (params.Size() != paramIndex)
+ IncorrectCommand();
+
+ HRESULT res = BenchCon(props2, numIterations, stdout);
+
+ if (res == S_OK)
+ return 0;
+ return Error_HRESULT("Benchmark error", res);
+ }
+
+ {
+ UInt32 needParams = 3;
+ if (stdInMode) needParams--;
+ if (stdOutMode) needParams--;
+ if (needParams != params.Size())
+ IncorrectCommand();
+ }
+
+ if (numThreads == (UInt32)(Int32)-1)
+ numThreads = 1;
+
+ bool encodeMode = false;
+
+ if (StringsAreEqualNoCase_Ascii(command, "e"))
+ encodeMode = true;
+ else if (!StringsAreEqualNoCase_Ascii(command, "d"))
+ IncorrectCommand();
+
+ CMyComPtr<ISequentialInStream> inStream;
+ CInFileStream *inStreamSpec = NULL;
+
+ if (stdInMode)
+ {
+ inStream = new CStdInFileStream;
+ MY_SET_BINARY_MODE(stdin);
+ }
+ else
+ {
+ const UString &inputName = params[paramIndex++];
+ inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ if (!inStreamSpec->Open(us2fs(inputName)))
+ {
+ PrintError2("can not open input file", inputName);
+ return 1;
+ }
+ }
+
+ CMyComPtr<ISequentialOutStream> outStream;
+ COutFileStream *outStreamSpec = NULL;
+
+ if (stdOutMode)
+ {
+ outStream = new CStdOutFileStream;
+ MY_SET_BINARY_MODE(stdout);
+ }
+ else
+ {
+ const UString &outputName = params[paramIndex++];
+ outStreamSpec = new COutFileStream;
+ outStream = outStreamSpec;
+ if (!outStreamSpec->Create(us2fs(outputName), true))
+ {
+ PrintError2("can not open output file", outputName);
+ return 1;
+ }
+ }
+
+ bool fileSizeDefined = false;
+ UInt64 fileSize = 0;
+
+ if (inStreamSpec)
+ {
+ if (!inStreamSpec->File.GetLength(fileSize))
+ throw "Can not get file length";
+ fileSizeDefined = true;
+ if (!stdOutMode)
+ Print_Size("Input size: ", fileSize);
+ }
+
+ if (encodeMode && !dictDefined)
+ {
+ dict = 1 << kDictSizeLog;
+ if (fileSizeDefined)
+ {
+ unsigned i;
+ for (i = 16; i < kDictSizeLog; i++)
+ if ((UInt32)((UInt32)1 << i) >= fileSize)
+ break;
+ dict = (UInt32)1 << i;
+ }
+ }
+
+ if (parser[NKey::kFilter86].ThereIs)
+ {
+ /* -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ It uses modified header format.
+ It's not recommended to use -f86 mode now.
+ You can use xz format instead, if you want to use filters */
+
+ if (parser[NKey::kEOS].ThereIs || stdInMode)
+ throw "Can not use stdin in this mode";
+
+ size_t inSize = (size_t)fileSize;
+
+ if (inSize != fileSize)
+ throw "File is too big";
+
+ Byte *inBuffer = NULL;
+
+ if (inSize != 0)
+ {
+ inBuffer = (Byte *)MyAlloc((size_t)inSize);
+ if (!inBuffer)
+ throw kCantAllocate;
+ }
+
+ if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)
+ throw "Can not read";
+
+ Byte *outBuffer = NULL;
+ size_t outSize;
+
+ if (encodeMode)
+ {
+ // we allocate 105% of original size for output buffer
+ UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);
+
+ outSize = (size_t)outSize64;
+
+ if (outSize != outSize64)
+ throw "File is too big";
+
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc((size_t)outSize);
+ if (!outBuffer)
+ throw kCantAllocate;
+ }
+
+ int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,
+ 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
+
+ if (res != 0)
+ {
+ PrintError_int("Encode error", (int)res);
+ return 1;
+ }
+ }
+ else
+ {
+ UInt64 outSize64;
+
+ if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)
+ throw "data error";
+
+ outSize = (size_t)outSize64;
+ if (outSize != outSize64)
+ throw "Unpack size is too big";
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc(outSize);
+ if (!outBuffer)
+ throw kCantAllocate;
+ }
+
+ int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);
+
+ if (inSize != (size_t)fileSize)
+ throw "incorrect processed size";
+ if (res != 0)
+ {
+ PrintError_int("Decode error", (int)res);
+ return 1;
+ }
+ }
+
+ if (WriteStream(outStream, outBuffer, outSize) != S_OK)
+ throw kWriteError;
+
+ MyFree(outBuffer);
+ MyFree(inBuffer);
+ }
+ else
+ {
+
+ CProgressPrint *progressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> progress;
+
+ if (!stdOutMode)
+ {
+ progressSpec = new CProgressPrint;
+ progress = progressSpec;
+ }
+
+ if (encodeMode)
+ {
+ NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ UInt32 pb = 2;
+ UInt32 lc = 3; // = 0; for 32-bit data
+ UInt32 lp = 0; // = 2; for 32-bit data
+ UInt32 algo = 1;
+ UInt32 fb = 128;
+ UInt32 mc = 16 + fb / 2;
+ bool mcDefined = false;
+
+ bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
+
+ ParseUInt32(parser, NKey::kAlgo, algo);
+ ParseUInt32(parser, NKey::kFb, fb);
+ ParseUInt32(parser, NKey::kLc, lc);
+ ParseUInt32(parser, NKey::kLp, lp);
+ ParseUInt32(parser, NKey::kPb, pb);
+
+ mcDefined = parser[NKey::kMc].ThereIs;
+ if (mcDefined)
+ mc = GetNumber(parser[NKey::kMc].PostStrings[0]);
+
+ const PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kPosStateBits,
+ NCoderPropID::kLitContextBits,
+ NCoderPropID::kLitPosBits,
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kNumFastBytes,
+ NCoderPropID::kMatchFinder,
+ NCoderPropID::kEndMarker,
+ NCoderPropID::kNumThreads,
+ NCoderPropID::kMatchFinderCycles,
+ };
+
+ const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);
+
+ PROPVARIANT props[kNumPropsMax];
+ for (int p = 0; p < 6; p++)
+ props[p].vt = VT_UI4;
+
+ props[0].ulVal = (UInt32)dict;
+ props[1].ulVal = (UInt32)pb;
+ props[2].ulVal = (UInt32)lc;
+ props[3].ulVal = (UInt32)lp;
+ props[4].ulVal = (UInt32)algo;
+ props[5].ulVal = (UInt32)fb;
+
+ props[6].vt = VT_BSTR;
+ props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);
+
+ props[7].vt = VT_BOOL;
+ props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
+
+ props[8].vt = VT_UI4;
+ props[8].ulVal = (UInt32)numThreads;
+
+ // it must be last in property list
+ props[9].vt = VT_UI4;
+ props[9].ulVal = (UInt32)mc;
+
+ unsigned numProps = kNumPropsMax;
+ if (!mcDefined)
+ numProps--;
+
+ HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);
+ if (res != S_OK)
+ return Error_HRESULT("incorrect encoder properties", res);
+
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+ throw kWriteError;
+
+ bool fileSizeWasUsed = true;
+ if (eos || stdInMode)
+ {
+ fileSize = (UInt64)(Int64)-1;
+ fileSizeWasUsed = false;
+ }
+
+ {
+ Byte temp[8];
+ for (int i = 0; i < 8; i++)
+ temp[i]= (Byte)(fileSize >> (8 * i));
+ if (WriteStream(outStream, temp, 8) != S_OK)
+ throw kWriteError;
+ }
+
+ res = encoder->Code(inStream, outStream, NULL, NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
+
+ if (res != S_OK)
+ return Error_HRESULT("Encoding error", res);
+
+ UInt64 processedSize = encoderSpec->GetInputProcessedSize();
+
+ if (fileSizeWasUsed && processedSize != fileSize)
+ throw "Incorrect size of processed data";
+ }
+ else
+ {
+ NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;
+ CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
+ decoderSpec->FinishStream = true;
+
+ const unsigned kPropertiesSize = 5;
+ Byte header[kPropertiesSize + 8];
+
+ if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
+ throw kReadError;
+
+ if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
+ throw "SetDecoderProperties error";
+
+ UInt64 unpackSize = 0;
+ for (int i = 0; i < 8; i++)
+ unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
+
+ bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1);
+
+ HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
+
+ if (res != S_OK)
+ {
+ if (res == S_FALSE)
+ {
+ PrintError("Decoding error");
+ return 1;
+ }
+ return Error_HRESULT("Decoding error", res);
+ }
+
+ if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize())
+ throw "incorrect uncompressed size in header";
+ }
+ }
+
+ if (outStreamSpec)
+ {
+ if (!stdOutMode)
+ Print_Size("Output size: ", outStreamSpec->ProcessedSize);
+ if (outStreamSpec->Close() != S_OK)
+ throw "File closing error";
+ }
+
+ return 0;
+}
+
+int MY_CDECL main(int numArgs, const char *args[])
+{
+ NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+
+ try { return main2(numArgs, args); }
+ catch (const char *s)
+ {
+ PrintError(s);
+ return 1;
+ }
+ catch(...)
+ {
+ PrintError("Unknown Error");
+ return 1;
+ }
+}