blob: f1d45f45ff65b4cacb5ccc5c7e3354a1b695efe0 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001--- /dev/null
2+++ b/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp
3@@ -0,0 +1,895 @@
4+/*
5+ * LZMA command line tool similar to gzip to encode and decode LZMA files.
6+ *
7+ * Copyright (C) 2005 Ville Koskinen
8+ *
9+ * This program is free software; you can redistribute it and/or
10+ * modify it under the terms of the GNU General Public License
11+ * as published by the Free Software Foundation; either version 2
12+ * of the License, or (at your option) any later version.
13+ *
14+ * This program is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program; if not, write to the Free Software
21+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22+ * USA.
23+ */
24+
25+#include "../../../Common/MyInitGuid.h"
26+
27+#include <iostream>
28+using std::cout;
29+using std::cerr;
30+using std::endl;
31+
32+#include <cstdio>
33+#include <cstdlib>
34+#include <cstring>
35+
36+#include <string>
37+using std::string;
38+#include <vector>
39+using std::vector;
40+typedef vector<string> stringVector;
41+
42+#include <unistd.h>
43+#include <getopt.h>
44+#include <signal.h>
45+
46+#include <sys/types.h>
47+#include <sys/stat.h>
48+#include <utime.h>
49+#include <sys/time.h> // futimes()
50+
51+// For Solaris
52+#ifndef HAVE_FUTIMES
53+//#define futimes(fd, tv) futimesat(fd, NULL, tv)
54+#endif
55+
56+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
57+#include <fcntl.h>
58+#include <io.h>
59+#define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
60+#else
61+#define MY_SET_BINARY_MODE(file)
62+#endif
63+
64+#include "../../../7zip/Common/FileStreams.h"
65+
66+#include "../../../Common/Types.h"
67+
68+#include "../../../7zip/Compress/LzmaDecoder.h"
69+#include "../../../7zip/Compress/LzmaEncoder.h"
70+
71+#include "Exception.h"
72+
73+#include "lzma_version.h"
74+
75+namespace lzma {
76+
77+const char *PROGRAM_VERSION = PACKAGE_VERSION;
78+const char *PROGRAM_COPYRIGHT = "Copyright (C) 2006 Ville Koskinen";
79+
80+/* LZMA_Alone switches:
81+ -a{N}: set compression mode - [0, 2], default: 2 (max)
82+ -d{N}: set dictionary - [0,28], default: 23 (8MB)
83+ -fb{N}: set number of fast bytes - [5, 255], default: 128
84+ -lc{N}: set number of literal context bits - [0, 8], default: 3
85+ -lp{N}: set number of literal pos bits - [0, 4], default: 0
86+ -pb{N}: set number of pos bits - [0, 4], default: 2
87+ -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,
88+ pat2h, pat3h, pat4h, hc3, hc4], default: bt4
89+*/
90+
91+struct lzma_option {
92+ short compression_mode; // -a
93+ short dictionary; // -d
94+ short fast_bytes; // -fb
95+ wchar_t *match_finder; // -mf
96+ short literal_context_bits; // -lc
97+ short literal_pos_bits; // -lp
98+ short pos_bits; // -pb
99+};
100+
101+/* The following is a mapping from gzip/bzip2 style -1 .. -9 compression modes
102+ * to the corresponding LZMA compression modes. Thanks, Larhzu, for coining
103+ * these. */
104+const lzma_option option_mapping[] = {
105+ { 0, 0, 0, NULL, 0, 0, 0}, // -0 (needed for indexing)
106+ { 0, 16, 64, L"hc4", 3, 0, 2}, // -1
107+ { 0, 20, 64, L"hc4", 3, 0, 2}, // -2
108+ { 1, 19, 64, L"bt4", 3, 0, 2}, // -3
109+ { 2, 20, 64, L"bt4", 3, 0, 2}, // -4
110+ { 2, 21, 128, L"bt4", 3, 0, 2}, // -5
111+ { 2, 22, 128, L"bt4", 3, 0, 2}, // -6
112+ { 2, 23, 128, L"bt4", 3, 0, 2}, // -7
113+ { 2, 24, 255, L"bt4", 3, 0, 2}, // -8
114+ { 2, 25, 255, L"bt4", 3, 0, 2}, // -9
115+};
116+
117+struct extension_pair {
118+ char *from;
119+ char *to;
120+};
121+
122+const extension_pair known_extensions[] = {
123+ { ".lzma", "" },
124+ { ".tlz", ".tar" },
125+ { NULL, NULL }
126+};
127+
128+/* Sorry, I just happen to like enumerations. */
129+enum PROGRAM_MODE {
130+ PM_COMPRESS = 0,
131+ PM_DECOMPRESS,
132+ PM_TEST,
133+ PM_HELP,
134+ PM_LICENSE,
135+ PM_VERSION
136+};
137+
138+enum {
139+ STATUS_OK = 0,
140+ STATUS_ERROR = 1,
141+ STATUS_WARNING = 2
142+};
143+
144+/* getopt options. */
145+/* struct option { name, has_arg, flag, val } */
146+const struct option long_options[] = {
147+ { "stdout", 0, 0, 'c' },
148+ { "decompress", 0, 0, 'd' },
149+ { "compress", 0, 0, 'z' },
150+ { "keep", 0, 0, 'k' },
151+ { "force", 0, 0, 'f' },
152+ { "test", 0, 0, 't' },
153+ { "suffix", 1, 0, 'S' },
154+ { "quiet", 0, 0, 'q' },
155+ { "verbose", 0, 0, 'v' },
156+ { "help", 0, 0, 'h' },
157+ { "license", 0, 0, 'L' },
158+ { "version", 0, 0, 'V' },
159+ { "fast", 0, 0, '1' },
160+ { "best", 0, 0, '9' },
161+ { 0, 0, 0, 0 }
162+};
163+
164+/* getopt option string (for the above options). */
165+const char option_string[] = "cdzkftS:qvhLV123456789A:D:F:";
166+
167+/* Defaults. */
168+PROGRAM_MODE program_mode = PM_COMPRESS;
169+int verbosity = 0;
170+bool stdinput = false;
171+bool stdoutput = false;
172+bool keep = false;
173+bool force = false;
174+int compression_mode = 7;
175+//char *suffix = strdup(".lzma");
176+char *suffix = strdup(known_extensions[0].from);
177+lzma_option advanced_options = { -1, -1, -1, NULL, -1, -1, -1 };
178+
179+void print_help(const char *const argv0)
180+{
181+ // Help goes to stdout while other messages go to stderr.
182+ cout << "\nlzma " << PROGRAM_VERSION
183+ << " " << PROGRAM_COPYRIGHT << "\n"
184+ "Based on LZMA SDK " << LZMA_SDK_VERSION_STRING << " "
185+ << LZMA_SDK_COPYRIGHT_STRING
186+ << "\n\nUsage: " << argv0
187+ << " [flags and input files in any order]\n"
188+" -c --stdout output to standard output\n"
189+" -d --decompress force decompression\n"
190+" -z --compress force compression\n"
191+" -k --keep keep (don't delete) input files\n"
192+" -f --force force overwrite of output file and compress links\n"
193+" -t --test test compressed file integrity\n"
194+" -S .suf --suffix .suf use suffix .suf on compressed files\n"
195+" -q --quiet suppress error messages\n"
196+" -v --verbose be verbose\n"
197+" -h --help print this message\n"
198+" -L --license display the license information\n"
199+" -V --version display version numbers of LZMA SDK and lzma\n"
200+" -1 .. -2 fast compression\n"
201+" -3 .. -9 good to excellent compression. -7 is the default.\n"
202+" --fast alias for -1\n"
203+" --best alias for -9 (usually *not* what you want)\n\n"
204+" Memory usage depends a lot on the chosen compression mode -1 .. -9.\n"
205+" See the man page lzma(1) for details.\n\n";
206+}
207+
208+void print_license(void)
209+{
210+ cout << "\n LZMA command line tool " << PROGRAM_VERSION << " - "
211+ << PROGRAM_COPYRIGHT
212+ << "\n LZMA SDK " << LZMA_SDK_VERSION_STRING << " - "
213+ << LZMA_SDK_COPYRIGHT_STRING
214+ << "\n This program is a part of the LZMA utils package.\n"
215+ " http://tukaani.org/lzma/\n\n"
216+" This program is free software; you can redistribute it and/or\n"
217+" modify it under the terms of the GNU General Public License\n"
218+" as published by the Free Software Foundation; either version 2\n"
219+" of the License, or (at your option) any later version.\n"
220+"\n"
221+" This program is distributed in the hope that it will be useful,\n"
222+" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
223+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
224+" GNU General Public License for more details.\n"
225+"\n";
226+}
227+
228+void print_version(void)
229+{
230+ cout << "LZMA command line tool " << PROGRAM_VERSION << "\n"
231+ << "LZMA SDK " << LZMA_SDK_VERSION_STRING << "\n";
232+}
233+
234+short str2int (const char *str, const int &min, const int &max)
235+{
236+ int value = -1;
237+ char *endptr = NULL;
238+ if (str == NULL || str[0] == '\0')
239+ throw ArgumentException("Invalid integer option");
240+ value = strtol (str, &endptr, 10);
241+ if (*endptr != '\0' || value < min || value > max)
242+ throw ArgumentException("Invalid integer option");
243+ return value;
244+}
245+
246+void parse_options(int argc, char **argv, stringVector &filenames)
247+{
248+ /* Snatched from getopt(3). */
249+ int c;
250+
251+ /* Check how we were called */
252+ {
253+ char *p = strrchr (argv[0], '/'); // Remove path prefix, if any
254+ if (p++ == NULL)
255+ p = argv[0];
256+ if (strstr (p, "un") != NULL) {
257+ program_mode = PM_DECOMPRESS;
258+ } else if (strstr (p, "cat") != NULL) {
259+ program_mode = PM_DECOMPRESS;
260+ stdoutput = true;
261+ }
262+ }
263+
264+ while (-1 != (c = getopt_long(argc, argv, option_string,
265+ long_options, NULL))) {
266+ switch (c) {
267+ // stdout
268+ case 'c':
269+ stdoutput = true;
270+ break;
271+
272+ // decompress
273+ case 'd':
274+ program_mode = PM_DECOMPRESS;
275+ break;
276+
277+ // compress
278+ case 'z':
279+ program_mode = PM_COMPRESS;
280+ break;
281+
282+ // keep
283+ case 'k':
284+ keep = true;
285+ break;
286+
287+ // force
288+ case 'f':
289+ force = true;
290+ break;
291+
292+ // test
293+ case 't':
294+ program_mode = PM_TEST;
295+ break;
296+
297+ // suffix
298+ case 'S':
299+ if (optarg) {
300+ free(suffix);
301+ suffix = strdup(optarg);
302+ }
303+ break;
304+
305+ // quiet
306+ case 'q':
307+ verbosity = 0;
308+ break;
309+
310+ // verbose
311+ case 'v':
312+ verbosity++;
313+ break;
314+
315+ // help
316+ case 'h':
317+ program_mode = PM_HELP;
318+ break;
319+
320+ // license
321+ case 'L':
322+ program_mode = PM_LICENSE;
323+ break;
324+
325+ // version
326+ case 'V':
327+ program_mode = PM_VERSION;
328+ break;
329+
330+ case '1': case '2': case '3': case '4': case '5':
331+ case '6': case '7': case '8': case '9':
332+ compression_mode = c - '0';
333+ break;
334+
335+ // Advanced options //
336+ // Compression mode
337+ case 'A':
338+ advanced_options.compression_mode =
339+ str2int (optarg, 0, 2);
340+ break;
341+
342+ // Dictionary size
343+ case 'D':
344+ advanced_options.dictionary =
345+ str2int (optarg, 0, 28);
346+ break;
347+
348+ // Fast bytes
349+ case 'F':
350+ advanced_options.fast_bytes =
351+ str2int (optarg, 0, 273);
352+ break;
353+
354+ default:
355+ throw ArgumentException("");
356+ break;
357+ } // switch(c)
358+ } // while(1)
359+
360+ for (int i = optind; i < argc; i++) {
361+ if (strcmp("-", argv[i]) == 0)
362+ continue;
363+ filenames.push_back(argv[i]);
364+ }
365+} // parse_options
366+
367+void set_encoder_properties(NCompress::NLzma::CEncoder *encoder,
368+ lzma_option &opt)
369+{
370+ /* Almost verbatim from LzmaAlone.cpp. */
371+ PROPID propIDs[] =
372+ {
373+ NCoderPropID::kDictionarySize,
374+ NCoderPropID::kPosStateBits,
375+ NCoderPropID::kLitContextBits,
376+ NCoderPropID::kLitPosBits,
377+ NCoderPropID::kAlgorithm,
378+ NCoderPropID::kNumFastBytes,
379+ NCoderPropID::kMatchFinder,
380+ NCoderPropID::kEndMarker
381+ };
382+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
383+#define VALUE(x) (advanced_options.x >= 0 ? advanced_options.x : opt.x)
384+ PROPVARIANT properties[kNumProps];
385+ for (int p = 0; p < 6; p++)
386+ properties[p].vt = VT_UI4;
387+ properties[0].ulVal = UInt32(1 << VALUE (dictionary));
388+ properties[1].ulVal = UInt32(VALUE (pos_bits));
389+ properties[2].ulVal = UInt32(VALUE (literal_context_bits));
390+ properties[3].ulVal = UInt32(VALUE (literal_pos_bits));
391+ properties[4].ulVal = UInt32(VALUE (compression_mode));
392+ properties[5].ulVal = UInt32(VALUE (fast_bytes));
393+#undef VALUE
394+
395+ properties[6].vt = VT_BSTR;
396+ properties[6].bstrVal = (BSTR)opt.match_finder;
397+
398+ properties[7].vt = VT_BOOL;
399+ properties[7].boolVal = stdinput ? VARIANT_TRUE : VARIANT_FALSE;
400+
401+ if (encoder->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
402+ throw Exception("SetCoderProperties() error");
403+}
404+
405+void encode(NCompress::NLzma::CEncoder *encoderSpec,
406+ CMyComPtr<ISequentialInStream> inStream,
407+ CMyComPtr<ISequentialOutStream> outStream,
408+ lzma_option encoder_options,
409+ UInt64 fileSize)
410+{
411+ set_encoder_properties(encoderSpec, encoder_options);
412+
413+ encoderSpec->WriteCoderProperties(outStream);
414+
415+ for (int i = 0; i < 8; i++)
416+ {
417+ Byte b = Byte(fileSize >> (8 * i));
418+ if (outStream->Write(&b, sizeof(b), 0) != S_OK)
419+ throw Exception("Write error while encoding");
420+ }
421+
422+ HRESULT result = encoderSpec->Code(inStream, outStream, 0, 0, 0);
423+
424+ if (result == E_OUTOFMEMORY)
425+ throw Exception("Cannot allocate memory");
426+ else if (result != S_OK) {
427+ char buffer[33];
428+ snprintf(buffer, 33, "%d", (unsigned int)result);
429+ throw Exception(string("Encoder error: ") + buffer);
430+ }
431+}
432+
433+void decode(NCompress::NLzma::CDecoder *decoderSpec,
434+ CMyComPtr<ISequentialInStream> inStream,
435+ CMyComPtr<ISequentialOutStream> outStream)
436+{
437+ const UInt32 kPropertiesSize = 5;
438+ Byte properties[kPropertiesSize];
439+ UInt32 processedSize;
440+ UInt64 fileSize = 0;
441+
442+ if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK)
443+ throw Exception("Read error");
444+ if (processedSize != kPropertiesSize)
445+ throw Exception("Read error");
446+ if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
447+ throw Exception("SetDecoderProperties() error");
448+
449+ for (int i = 0; i < 8; i++)
450+ {
451+ Byte b;
452+
453+ if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK)
454+ throw Exception("Read error");
455+ if (processedSize != 1)
456+ throw Exception("Read error");
457+
458+ fileSize |= ((UInt64)b) << (8 * i);
459+ }
460+
461+ if (decoderSpec->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
462+ throw Exception("Decoder error");
463+}
464+
465+int open_instream(const string infile,
466+ CMyComPtr<ISequentialInStream> &inStream,
467+ UInt64 &fileSize)
468+{
469+ CInFileStream *inStreamSpec = new CInFileStream;
470+ inStream = inStreamSpec;
471+ if (!inStreamSpec->Open(infile.c_str()))
472+ throw Exception("Cannot open input file " + infile);
473+
474+ inStreamSpec->File.GetLength(fileSize);
475+
476+ return inStreamSpec->File.GetHandle();
477+}
478+
479+int open_outstream(const string outfile,
480+ CMyComPtr<ISequentialOutStream> &outStream)
481+{
482+ COutFileStream *outStreamSpec = new COutFileStream;
483+ outStream = outStreamSpec;
484+
485+ bool open_by_force = (program_mode == PM_TEST) | force;
486+
487+ if (!outStreamSpec->Create(outfile.c_str(), open_by_force))
488+ throw Exception("Cannot open output file " + outfile);
489+
490+ return outStreamSpec->File.GetHandle();
491+}
492+
493+double get_ratio(int inhandle, int outhandle)
494+{
495+ struct stat in_stats, out_stats;
496+ fstat(inhandle, &in_stats);
497+ fstat(outhandle, &out_stats);
498+
499+ return (double)out_stats.st_size / (double)in_stats.st_size;
500+}
501+
502+mode_t get_file_mode(string filename)
503+{
504+ struct stat in_stat;
505+ lstat(filename.c_str(), &in_stat);
506+
507+ return in_stat.st_mode;
508+}
509+
510+bool string_ends_with(string str, string ending)
511+{
512+ return equal(ending.rbegin(), ending.rend(), str.rbegin());
513+}
514+
515+bool extension_is_known(string filename)
516+{
517+ bool known_format = false;
518+ extension_pair extension; int i = 1;
519+
520+ extension = known_extensions[0];
521+ while (extension.from != NULL) {
522+ if (string_ends_with(filename, extension.from)) {
523+ known_format = true;
524+ break;
525+ }
526+ extension = known_extensions[i];
527+ i++;
528+ }
529+
530+ if (!known_format) {
531+ if (!string_ends_with(filename, suffix)) {
532+ return false;
533+ }
534+ }
535+
536+ return true;
537+}
538+
539+string replace_extension(string filename)
540+{
541+ int suffix_starts_at = filename.length() - strlen (suffix);
542+ string from_suffix = filename.substr(suffix_starts_at, strlen (suffix));
543+ string ret = filename.substr(0, suffix_starts_at);
544+ extension_pair extension; int i = 1;
545+
546+ bool found_replacement = false;
547+ extension = known_extensions[0];
548+ while (extension.from != NULL) {
549+ if (from_suffix.compare(extension.from) == 0) {
550+ ret += extension.to;
551+ found_replacement = true;
552+ break;
553+ }
554+
555+ extension = known_extensions[i];
556+ i++;
557+ }
558+
559+ return ret;
560+}
561+
562+string pretty_print_status(string filename, string output_filename,
563+ string ratio)
564+{
565+ string ret = "";
566+
567+ ret += filename;
568+ ret += ":\t ";
569+
570+ if (program_mode == PM_TEST) {
571+ ret += "decoded succesfully";
572+
573+ return ret;
574+ }
575+
576+ if (!stdinput && !stdoutput) {
577+ ret += ratio;
578+ ret += " -- ";
579+ }
580+
581+ if (program_mode == PM_COMPRESS) {
582+ if (keep) {
583+ ret += "encoded succesfully";
584+
585+ return ret;
586+ }
587+
588+ ret += "replaced with ";
589+ ret += output_filename;
590+
591+ return ret;
592+ }
593+
594+ if (program_mode == PM_DECOMPRESS) {
595+ if (keep) {
596+ ret += "decoded succesfully";
597+
598+ return ret;
599+ }
600+
601+ ret += "replaced with ";
602+ ret += output_filename;
603+
604+ return ret;
605+ }
606+
607+ return ret;
608+}
609+
610+static string archive_name; // I know, it is crude, but I haven't found any other
611+ // way then making a global variable to transfer filename to handler
612+
613+void signal_handler (int signum)
614+{
615+ unlink (archive_name.c_str()); // deleting
616+ signal (signum, SIG_DFL); // we return the default function to used signal
617+ kill (getpid(), signum); // and then send this signal to the process again
618+}
619+
620+} // namespace lzma
621+
622+
623+int main(int argc, char **argv)
624+{
625+ using namespace lzma;
626+ using std::cerr;
627+
628+ stringVector filenames;
629+
630+ signal (SIGTERM,signal_handler);
631+ signal (SIGHUP,signal_handler);
632+ signal (SIGINT,signal_handler);
633+
634+ try {
635+ parse_options(argc, argv, filenames);
636+ }
637+ catch (...) {
638+ return STATUS_ERROR;
639+ }
640+
641+ if (program_mode == PM_HELP) {
642+ print_help(argv[0]);
643+ return STATUS_OK;
644+ }
645+ else if (program_mode == PM_LICENSE) {
646+ print_license();
647+ return STATUS_OK;
648+ }
649+ else if (program_mode == PM_VERSION) {
650+ print_version();
651+ return STATUS_OK;
652+ }
653+
654+ if (filenames.empty()) {
655+ stdinput = true;
656+ stdoutput = true;
657+
658+ /* FIXME: get rid of this */
659+ filenames.push_back("-");
660+ }
661+
662+ /* Protection: always create new files with 0600 in order to prevent
663+ * outsiders from reading incomplete data. */
664+ umask(0077);
665+
666+ bool warning = false;
667+
668+ for (int i = 0; i < filenames.size(); i++) {
669+ CMyComPtr<ISequentialInStream> inStream;
670+ CMyComPtr<ISequentialOutStream> outStream;
671+ UInt64 fileSize = 0;
672+ int inhandle = 0, outhandle = 0;
673+ string output_filename;
674+
675+ if (stdinput) {
676+ inStream = new CStdInFileStream;
677+ MY_SET_BINARY_MODE(stdin);
678+ fileSize = (UInt64)(Int64)-1;
679+
680+ inhandle = STDIN_FILENO;
681+
682+ outStream = new CStdOutFileStream;
683+ MY_SET_BINARY_MODE(stdout);
684+
685+ outhandle = STDOUT_FILENO;
686+ }
687+ else {
688+ mode_t infile_mode = get_file_mode(filenames[i]);
689+ if (!S_ISREG(infile_mode)) {
690+ if (S_ISDIR(infile_mode)) {
691+ warning = true;
692+ cerr << argv[0] << ": " << filenames[i] << ": "
693+ << "cowardly refusing to work on directory"
694+ << endl;
695+
696+ continue;
697+ }
698+ else if (S_ISLNK(infile_mode)) {
699+ if (!stdoutput && !force) {
700+ warning = true;
701+
702+ cerr << argv[0] << ": " << filenames[i] << ": "
703+ << "cowardly refusing to work on symbolic link "
704+ << "(use --force to force encoding or decoding)"
705+ << endl;
706+
707+ continue;
708+ }
709+ }
710+ else {
711+ warning = true;
712+
713+ cerr << argv[0] << ": " << filenames[i] << ": "
714+ << "doesn't exist or is not a regular file"
715+ << endl;
716+
717+ continue;
718+ }
719+ }
720+
721+ // Test if the file already ends with *suffix.
722+ if (program_mode == PM_COMPRESS && !force
723+ && string_ends_with(filenames[i],
724+ suffix)) {
725+ warning = true;
726+
727+ cerr << filenames[i] << " already has "
728+ << suffix << " suffix -- unchanged\n";
729+
730+ continue;
731+ }
732+
733+ // Test if the file extension is known.
734+ if (program_mode == PM_DECOMPRESS
735+ && !extension_is_known(filenames[i])) {
736+ warning = true;
737+
738+ cerr << filenames[i] << ": "
739+ << " unknown suffix -- unchanged"
740+ << endl;
741+
742+ continue;
743+ }
744+
745+ try {
746+ inhandle = open_instream(filenames[i], inStream, fileSize);
747+ }
748+ catch (Exception e) {
749+ cerr << argv[0] << ": " << e.what() << endl;
750+ return STATUS_ERROR;
751+ }
752+
753+ if (stdoutput) {
754+ outStream = new CStdOutFileStream;
755+ MY_SET_BINARY_MODE(stdout);
756+
757+ outhandle = STDOUT_FILENO;
758+ }
759+ else {
760+ /* Testing mode is nothing else but decoding
761+ * and throwing away the result. */
762+ if (program_mode == PM_TEST)
763+ output_filename = "/dev/null";
764+ else if (program_mode == PM_DECOMPRESS)
765+ output_filename = replace_extension(filenames[i]);
766+ else
767+ output_filename = filenames[i]
768+ + suffix;
769+ archive_name = output_filename;
770+
771+ try {
772+ outhandle = open_outstream(output_filename, outStream);
773+ }
774+ catch (Exception e) {
775+ cerr << argv[0] << ": " << e.what() << endl;
776+ return STATUS_ERROR;
777+ }
778+ }
779+
780+ }
781+
782+ // Unless --force is specified, do not read/write compressed
783+ // data from/to a terminal.
784+ if (!force) {
785+ if (program_mode == PM_COMPRESS && isatty(outhandle)) {
786+ cerr << argv[0] << ": compressed data not "
787+ "written to a terminal. Use "
788+ "-f to force compression.\n"
789+ << argv[0] << ": For help, type: "
790+ << argv[0] << " -h\n";
791+ return STATUS_ERROR;
792+ } else if (program_mode == PM_DECOMPRESS
793+ && isatty(inhandle)) {
794+ cerr << argv[0] << ": compressed data not "
795+ "read from a terminal. Use "
796+ "-f to force decompression.\n"
797+ << argv[0] << ": For help, type: "
798+ << argv[0] << " -h\n";
799+ return STATUS_ERROR;
800+ }
801+ }
802+
803+ if (program_mode == PM_COMPRESS) {
804+ NCompress::NLzma::CEncoder *encoderSpec =
805+ new NCompress::NLzma::CEncoder;
806+
807+ lzma_option options = option_mapping[compression_mode];
808+
809+ try {
810+ encode(encoderSpec, inStream, outStream, options, fileSize);
811+ }
812+ catch (Exception e) {
813+ cerr << argv[0] << ": " << e.what() << endl;
814+ unlink(output_filename.c_str());
815+ delete(encoderSpec);
816+
817+ return STATUS_ERROR;
818+ }
819+
820+ delete(encoderSpec);
821+ }
822+ else { // PM_DECOMPRESS | PM_TEST
823+ NCompress::NLzma::CDecoder *decoderSpec =
824+ new NCompress::NLzma::CDecoder;
825+
826+ try {
827+ decode(decoderSpec, inStream, outStream);
828+ }
829+ catch (Exception e) {
830+ cerr << argv[0] << ": " << e.what() << endl;
831+ unlink(output_filename.c_str());
832+ delete(decoderSpec);
833+
834+ return STATUS_ERROR;
835+ }
836+
837+ delete(decoderSpec);
838+ }
839+
840+ /* Set permissions and owners. */
841+ if ( (program_mode == PM_COMPRESS || program_mode == PM_DECOMPRESS )
842+ && (!stdinput && !stdoutput) ) {
843+
844+ int ret = 0;
845+ struct stat file_stats;
846+ ret = fstat(inhandle, &file_stats);
847+
848+ ret = fchmod(outhandle, file_stats.st_mode);
849+ ret = fchown(outhandle, file_stats.st_uid, file_stats.st_gid);
850+ // We need to call fchmod() again, since otherwise the SUID bits
851+ // are lost.
852+ ret = fchmod(outhandle, file_stats.st_mode);
853+
854+ struct timeval file_times[2];
855+ // Access time
856+ file_times[0].tv_sec = file_stats.st_atime;
857+ file_times[0].tv_usec = 0;
858+ // Modification time
859+ file_times[1].tv_sec = file_stats.st_mtime;
860+ file_times[1].tv_usec = 0;
861+
862+ ret = futimes(outhandle, file_times);
863+
864+ if (!keep)
865+ unlink(filenames[i].c_str());
866+ }
867+
868+ if (verbosity > 0) {
869+ if (stdoutput) {
870+ cerr << filenames[i] << ":\t ";
871+ cerr << "decoded succesfully"
872+ << endl;
873+ }
874+
875+ else {
876+ char buf[10] = { 0 };
877+
878+ if (program_mode == PM_DECOMPRESS)
879+ snprintf(buf, 10, "%.2f%%",
880+ (1 - get_ratio(outhandle, inhandle)) * 100);
881+ if (program_mode == PM_COMPRESS)
882+ snprintf(buf, 10, "%.2f%%",
883+ (1 - get_ratio(inhandle, outhandle)) * 100);
884+
885+ string ratio = buf;
886+ cerr << pretty_print_status(filenames[i], output_filename,
887+ ratio)
888+ << endl;
889+ }
890+ }
891+ }
892+
893+ if (warning)
894+ return STATUS_WARNING;
895+
896+ return STATUS_OK;
897+}
898+
899--- /dev/null
900+++ b/CPP/7zip/Compress/LZMA_Alone/Exception.h
901@@ -0,0 +1,45 @@
902+/* A couple of exceptions for lzmp.
903+ *
904+ * Copyright (C) 2005 Ville Koskinen
905+ *
906+ * This program is free software; you can redistribute it and/or
907+ * modify it under the terms of the GNU General Public License
908+ * as published by the Free Software Foundation; either version 2
909+ * of the License, or (at your option) any later version.
910+ *
911+ * This program is distributed in the hope that it will be useful,
912+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
913+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
914+ * GNU General Public License for more details.
915+ */
916+
917+#ifndef _EXCEPTION_H_
918+#define _EXCEPTION_H_
919+
920+#include <string>
921+using std::string;
922+
923+class Exception
924+{
925+private:
926+ string message;
927+public:
928+ Exception(char *what): message(what) { }
929+ Exception(string what): message(what) { }
930+
931+ ~Exception() { }
932+
933+ string what(void) { return message; }
934+};
935+
936+class ArgumentException: public Exception
937+{
938+public:
939+ ArgumentException(char *what): Exception(what) { }
940+ ArgumentException(string what): Exception(what) { }
941+
942+ ~ArgumentException() { }
943+};
944+
945+#endif
946+
947--- a/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
948+++ b/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
949@@ -1,9 +1,10 @@
950-PROG = lzma
951+PROG = lzma_alone
952+PROG2 = lzma
953 CXX = g++ -O2 -Wall
954 CXX_C = gcc -O2 -Wall
955 LIB = -lm
956 RM = rm -f
957-CFLAGS = -c -D_FILE_OFFSET_BITS=64
958+CFLAGS = -c -I ../../../ -D_FILE_OFFSET_BITS=64 -DPACKAGE_VERSION="\"4.32.0beta3\""
959
960 ifdef SystemDrive
961 IS_MINGW = 1
962@@ -45,12 +46,35 @@ OBJS = \
963 Lzma86Dec.o \
964 Lzma86Enc.o \
965
966+OBJS2 = \
967+ C_FileIO.o \
968+ CRC.o \
969+ Alloc.o \
970+ FileStreams.o \
971+ StreamUtils.o \
972+ InBuffer.o \
973+ OutBuffer.o \
974+ LzmaDecoder.o \
975+ StringConvert.o \
976+ StringToInt.o \
977+ LzmaEncoder.o \
978+ LzmaDec.o \
979+ LzmaEnc.o \
980+ LzFind.o \
981+ 7zCrc.o \
982+ lzmp.o
983
984-all: $(PROG)
985+all: $(PROG) $(PROG2)
986
987 $(PROG): $(OBJS)
988 $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
989
990+$(PROG2): $(OBJS2)
991+ $(CXX) -o $(PROG2) $(LDFLAGS) $(OBJS2) $(LIB)
992+
993+lzmp.o: lzmp.cpp
994+ $(CXX) $(CFLAGS) lzmp.cpp
995+
996 LzmaAlone.o: LzmaAlone.cpp
997 $(CXX) $(CFLAGS) LzmaAlone.cpp
998
999@@ -131,5 +155,5 @@ Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma
1000 $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c
1001
1002 clean:
1003- -$(RM) $(PROG) $(OBJS)
1004+ -$(RM) $(PROG) $(PROG2) $(OBJS)
1005
1006--- /dev/null
1007+++ b/CPP/7zip/Compress/LZMA_Alone/lzma_version.h
1008@@ -0,0 +1,31 @@
1009+#ifndef LZMA_VERSION_H
1010+#define LZMA_VERSION_H
1011+
1012+/*
1013+ Version and copyright information used by LZMA utils.
1014+*/
1015+
1016+static const char *LZMA_SDK_VERSION_STRING = "4.43";
1017+
1018+static const char *LZMA_SDK_COPYRIGHT_STRING =
1019+ "Copyright (C) 1999-2006 Igor Pavlov";
1020+
1021+static const char *LZMA_SDK_COPYRIGHT_INFO =
1022+ " See http://7-zip.org/sdk.html or the documentation of LZMA SDK for\n"
1023+ " the license. For reference, the version 4.43 is free software\n"
1024+ " licensed under the GNU LGPL.";
1025+
1026+
1027+static const char *LZMA_UTILS_VERSION_STRING = PACKAGE_VERSION;
1028+
1029+static const char *LZMA_UTILS_COPYRIGHT_STRING =
1030+ "Copyright (C) 2006 Lasse Collin";
1031+
1032+static const char *LZMA_UTILS_COPYRIGHT_INFO =
1033+ "This program comes with ABSOLUTELY NO WARRANTY.\n"
1034+ "You may redistribute copies of this program\n"
1035+ "under the terms of the GNU General Public License.\n"
1036+ "For more information about these matters, see the file "
1037+ "named COPYING.\n";
1038+
1039+#endif /* ifndef LZMA_VERSION_H */
1040--- a/CPP/Common/C_FileIO.h
1041+++ b/CPP/Common/C_FileIO.h
1042@@ -24,6 +24,7 @@ public:
1043 bool Close();
1044 bool GetLength(UInt64 &length) const;
1045 off_t Seek(off_t distanceToMove, int moveMethod) const;
1046+ int GetHandle() const { return _handle; }
1047 };
1048
1049 class CInFile: public CFileBase