mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-01 00:49:42 +02:00
1060 lines
27 KiB
Diff
1060 lines
27 KiB
Diff
|
Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp 2009-06-01 22:01:10.000000000 +0200
|
||
|
@@ -0,0 +1,895 @@
|
||
|
+/*
|
||
|
+ * LZMA command line tool similar to gzip to encode and decode LZMA files.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2005 Ville Koskinen
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or
|
||
|
+ * modify it under the terms of the GNU General Public License
|
||
|
+ * as published by the Free Software Foundation; either version 2
|
||
|
+ * 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 General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this program; if not, write to the Free Software
|
||
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||
|
+ * USA.
|
||
|
+ */
|
||
|
+
|
||
|
+#include "../../../Common/MyInitGuid.h"
|
||
|
+
|
||
|
+#include <iostream>
|
||
|
+using std::cout;
|
||
|
+using std::cerr;
|
||
|
+using std::endl;
|
||
|
+
|
||
|
+#include <cstdio>
|
||
|
+#include <cstdlib>
|
||
|
+#include <cstring>
|
||
|
+
|
||
|
+#include <string>
|
||
|
+using std::string;
|
||
|
+#include <vector>
|
||
|
+using std::vector;
|
||
|
+typedef vector<string> stringVector;
|
||
|
+
|
||
|
+#include <unistd.h>
|
||
|
+#include <getopt.h>
|
||
|
+#include <signal.h>
|
||
|
+
|
||
|
+#include <sys/types.h>
|
||
|
+#include <sys/stat.h>
|
||
|
+#include <utime.h>
|
||
|
+#include <sys/time.h> // futimes()
|
||
|
+
|
||
|
+// For Solaris
|
||
|
+#ifndef HAVE_FUTIMES
|
||
|
+//#define futimes(fd, tv) futimesat(fd, NULL, tv)
|
||
|
+#endif
|
||
|
+
|
||
|
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
|
||
|
+#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 "../../../7zip/Common/FileStreams.h"
|
||
|
+
|
||
|
+#include "../../../Common/Types.h"
|
||
|
+
|
||
|
+#include "../../../7zip/Compress/LzmaDecoder.h"
|
||
|
+#include "../../../7zip/Compress/LzmaEncoder.h"
|
||
|
+
|
||
|
+#include "Exception.h"
|
||
|
+
|
||
|
+#include "lzma_version.h"
|
||
|
+
|
||
|
+namespace lzma {
|
||
|
+
|
||
|
+const char *PROGRAM_VERSION = PACKAGE_VERSION;
|
||
|
+const char *PROGRAM_COPYRIGHT = "Copyright (C) 2006 Ville Koskinen";
|
||
|
+
|
||
|
+/* LZMA_Alone switches:
|
||
|
+ -a{N}: set compression mode - [0, 2], default: 2 (max)
|
||
|
+ -d{N}: set dictionary - [0,28], default: 23 (8MB)
|
||
|
+ -fb{N}: set number of fast bytes - [5, 255], default: 128
|
||
|
+ -lc{N}: set number of literal context bits - [0, 8], default: 3
|
||
|
+ -lp{N}: set number of literal pos bits - [0, 4], default: 0
|
||
|
+ -pb{N}: set number of pos bits - [0, 4], default: 2
|
||
|
+ -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,
|
||
|
+ pat2h, pat3h, pat4h, hc3, hc4], default: bt4
|
||
|
+*/
|
||
|
+
|
||
|
+struct lzma_option {
|
||
|
+ short compression_mode; // -a
|
||
|
+ short dictionary; // -d
|
||
|
+ short fast_bytes; // -fb
|
||
|
+ wchar_t *match_finder; // -mf
|
||
|
+ short literal_context_bits; // -lc
|
||
|
+ short literal_pos_bits; // -lp
|
||
|
+ short pos_bits; // -pb
|
||
|
+};
|
||
|
+
|
||
|
+/* The following is a mapping from gzip/bzip2 style -1 .. -9 compression modes
|
||
|
+ * to the corresponding LZMA compression modes. Thanks, Larhzu, for coining
|
||
|
+ * these. */
|
||
|
+const lzma_option option_mapping[] = {
|
||
|
+ { 0, 0, 0, NULL, 0, 0, 0}, // -0 (needed for indexing)
|
||
|
+ { 0, 16, 64, L"hc4", 3, 0, 2}, // -1
|
||
|
+ { 0, 20, 64, L"hc4", 3, 0, 2}, // -2
|
||
|
+ { 1, 19, 64, L"bt4", 3, 0, 2}, // -3
|
||
|
+ { 2, 20, 64, L"bt4", 3, 0, 2}, // -4
|
||
|
+ { 2, 21, 128, L"bt4", 3, 0, 2}, // -5
|
||
|
+ { 2, 22, 128, L"bt4", 3, 0, 2}, // -6
|
||
|
+ { 2, 23, 128, L"bt4", 3, 0, 2}, // -7
|
||
|
+ { 2, 24, 255, L"bt4", 3, 0, 2}, // -8
|
||
|
+ { 2, 25, 255, L"bt4", 3, 0, 2}, // -9
|
||
|
+};
|
||
|
+
|
||
|
+struct extension_pair {
|
||
|
+ char *from;
|
||
|
+ char *to;
|
||
|
+};
|
||
|
+
|
||
|
+const extension_pair known_extensions[] = {
|
||
|
+ { ".lzma", "" },
|
||
|
+ { ".tlz", ".tar" },
|
||
|
+ { NULL, NULL }
|
||
|
+};
|
||
|
+
|
||
|
+/* Sorry, I just happen to like enumerations. */
|
||
|
+enum PROGRAM_MODE {
|
||
|
+ PM_COMPRESS = 0,
|
||
|
+ PM_DECOMPRESS,
|
||
|
+ PM_TEST,
|
||
|
+ PM_HELP,
|
||
|
+ PM_LICENSE,
|
||
|
+ PM_VERSION
|
||
|
+};
|
||
|
+
|
||
|
+enum {
|
||
|
+ STATUS_OK = 0,
|
||
|
+ STATUS_ERROR = 1,
|
||
|
+ STATUS_WARNING = 2
|
||
|
+};
|
||
|
+
|
||
|
+/* getopt options. */
|
||
|
+/* struct option { name, has_arg, flag, val } */
|
||
|
+const struct option long_options[] = {
|
||
|
+ { "stdout", 0, 0, 'c' },
|
||
|
+ { "decompress", 0, 0, 'd' },
|
||
|
+ { "compress", 0, 0, 'z' },
|
||
|
+ { "keep", 0, 0, 'k' },
|
||
|
+ { "force", 0, 0, 'f' },
|
||
|
+ { "test", 0, 0, 't' },
|
||
|
+ { "suffix", 1, 0, 'S' },
|
||
|
+ { "quiet", 0, 0, 'q' },
|
||
|
+ { "verbose", 0, 0, 'v' },
|
||
|
+ { "help", 0, 0, 'h' },
|
||
|
+ { "license", 0, 0, 'L' },
|
||
|
+ { "version", 0, 0, 'V' },
|
||
|
+ { "fast", 0, 0, '1' },
|
||
|
+ { "best", 0, 0, '9' },
|
||
|
+ { 0, 0, 0, 0 }
|
||
|
+};
|
||
|
+
|
||
|
+/* getopt option string (for the above options). */
|
||
|
+const char option_string[] = "cdzkftS:qvhLV123456789A:D:F:";
|
||
|
+
|
||
|
+/* Defaults. */
|
||
|
+PROGRAM_MODE program_mode = PM_COMPRESS;
|
||
|
+int verbosity = 0;
|
||
|
+bool stdinput = false;
|
||
|
+bool stdoutput = false;
|
||
|
+bool keep = false;
|
||
|
+bool force = false;
|
||
|
+int compression_mode = 7;
|
||
|
+//char *suffix = strdup(".lzma");
|
||
|
+char *suffix = strdup(known_extensions[0].from);
|
||
|
+lzma_option advanced_options = { -1, -1, -1, NULL, -1, -1, -1 };
|
||
|
+
|
||
|
+void print_help(const char *const argv0)
|
||
|
+{
|
||
|
+ // Help goes to stdout while other messages go to stderr.
|
||
|
+ cout << "\nlzma " << PROGRAM_VERSION
|
||
|
+ << " " << PROGRAM_COPYRIGHT << "\n"
|
||
|
+ "Based on LZMA SDK " << LZMA_SDK_VERSION_STRING << " "
|
||
|
+ << LZMA_SDK_COPYRIGHT_STRING
|
||
|
+ << "\n\nUsage: " << argv0
|
||
|
+ << " [flags and input files in any order]\n"
|
||
|
+" -c --stdout output to standard output\n"
|
||
|
+" -d --decompress force decompression\n"
|
||
|
+" -z --compress force compression\n"
|
||
|
+" -k --keep keep (don't delete) input files\n"
|
||
|
+" -f --force force overwrite of output file and compress links\n"
|
||
|
+" -t --test test compressed file integrity\n"
|
||
|
+" -S .suf --suffix .suf use suffix .suf on compressed files\n"
|
||
|
+" -q --quiet suppress error messages\n"
|
||
|
+" -v --verbose be verbose\n"
|
||
|
+" -h --help print this message\n"
|
||
|
+" -L --license display the license information\n"
|
||
|
+" -V --version display version numbers of LZMA SDK and lzma\n"
|
||
|
+" -1 .. -2 fast compression\n"
|
||
|
+" -3 .. -9 good to excellent compression. -7 is the default.\n"
|
||
|
+" --fast alias for -1\n"
|
||
|
+" --best alias for -9 (usually *not* what you want)\n\n"
|
||
|
+" Memory usage depends a lot on the chosen compression mode -1 .. -9.\n"
|
||
|
+" See the man page lzma(1) for details.\n\n";
|
||
|
+}
|
||
|
+
|
||
|
+void print_license(void)
|
||
|
+{
|
||
|
+ cout << "\n LZMA command line tool " << PROGRAM_VERSION << " - "
|
||
|
+ << PROGRAM_COPYRIGHT
|
||
|
+ << "\n LZMA SDK " << LZMA_SDK_VERSION_STRING << " - "
|
||
|
+ << LZMA_SDK_COPYRIGHT_STRING
|
||
|
+ << "\n This program is a part of the LZMA utils package.\n"
|
||
|
+ " http://tukaani.org/lzma/\n\n"
|
||
|
+" This program is free software; you can redistribute it and/or\n"
|
||
|
+" modify it under the terms of the GNU General Public License\n"
|
||
|
+" as published by the Free Software Foundation; either version 2\n"
|
||
|
+" of the License, or (at your option) any later version.\n"
|
||
|
+"\n"
|
||
|
+" This program is distributed in the hope that it will be useful,\n"
|
||
|
+" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||
|
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||
|
+" GNU General Public License for more details.\n"
|
||
|
+"\n";
|
||
|
+}
|
||
|
+
|
||
|
+void print_version(void)
|
||
|
+{
|
||
|
+ cout << "LZMA command line tool " << PROGRAM_VERSION << "\n"
|
||
|
+ << "LZMA SDK " << LZMA_SDK_VERSION_STRING << "\n";
|
||
|
+}
|
||
|
+
|
||
|
+short str2int (const char *str, const int &min, const int &max)
|
||
|
+{
|
||
|
+ int value = -1;
|
||
|
+ char *endptr = NULL;
|
||
|
+ if (str == NULL || str[0] == '\0')
|
||
|
+ throw ArgumentException("Invalid integer option");
|
||
|
+ value = strtol (str, &endptr, 10);
|
||
|
+ if (*endptr != '\0' || value < min || value > max)
|
||
|
+ throw ArgumentException("Invalid integer option");
|
||
|
+ return value;
|
||
|
+}
|
||
|
+
|
||
|
+void parse_options(int argc, char **argv, stringVector &filenames)
|
||
|
+{
|
||
|
+ /* Snatched from getopt(3). */
|
||
|
+ int c;
|
||
|
+
|
||
|
+ /* Check how we were called */
|
||
|
+ {
|
||
|
+ char *p = strrchr (argv[0], '/'); // Remove path prefix, if any
|
||
|
+ if (p++ == NULL)
|
||
|
+ p = argv[0];
|
||
|
+ if (strstr (p, "un") != NULL) {
|
||
|
+ program_mode = PM_DECOMPRESS;
|
||
|
+ } else if (strstr (p, "cat") != NULL) {
|
||
|
+ program_mode = PM_DECOMPRESS;
|
||
|
+ stdoutput = true;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ while (-1 != (c = getopt_long(argc, argv, option_string,
|
||
|
+ long_options, NULL))) {
|
||
|
+ switch (c) {
|
||
|
+ // stdout
|
||
|
+ case 'c':
|
||
|
+ stdoutput = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // decompress
|
||
|
+ case 'd':
|
||
|
+ program_mode = PM_DECOMPRESS;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // compress
|
||
|
+ case 'z':
|
||
|
+ program_mode = PM_COMPRESS;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // keep
|
||
|
+ case 'k':
|
||
|
+ keep = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // force
|
||
|
+ case 'f':
|
||
|
+ force = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // test
|
||
|
+ case 't':
|
||
|
+ program_mode = PM_TEST;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // suffix
|
||
|
+ case 'S':
|
||
|
+ if (optarg) {
|
||
|
+ free(suffix);
|
||
|
+ suffix = strdup(optarg);
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ // quiet
|
||
|
+ case 'q':
|
||
|
+ verbosity = 0;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // verbose
|
||
|
+ case 'v':
|
||
|
+ verbosity++;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // help
|
||
|
+ case 'h':
|
||
|
+ program_mode = PM_HELP;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // license
|
||
|
+ case 'L':
|
||
|
+ program_mode = PM_LICENSE;
|
||
|
+ break;
|
||
|
+
|
||
|
+ // version
|
||
|
+ case 'V':
|
||
|
+ program_mode = PM_VERSION;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case '1': case '2': case '3': case '4': case '5':
|
||
|
+ case '6': case '7': case '8': case '9':
|
||
|
+ compression_mode = c - '0';
|
||
|
+ break;
|
||
|
+
|
||
|
+ // Advanced options //
|
||
|
+ // Compression mode
|
||
|
+ case 'A':
|
||
|
+ advanced_options.compression_mode =
|
||
|
+ str2int (optarg, 0, 2);
|
||
|
+ break;
|
||
|
+
|
||
|
+ // Dictionary size
|
||
|
+ case 'D':
|
||
|
+ advanced_options.dictionary =
|
||
|
+ str2int (optarg, 0, 28);
|
||
|
+ break;
|
||
|
+
|
||
|
+ // Fast bytes
|
||
|
+ case 'F':
|
||
|
+ advanced_options.fast_bytes =
|
||
|
+ str2int (optarg, 0, 273);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ throw ArgumentException("");
|
||
|
+ break;
|
||
|
+ } // switch(c)
|
||
|
+ } // while(1)
|
||
|
+
|
||
|
+ for (int i = optind; i < argc; i++) {
|
||
|
+ if (strcmp("-", argv[i]) == 0)
|
||
|
+ continue;
|
||
|
+ filenames.push_back(argv[i]);
|
||
|
+ }
|
||
|
+} // parse_options
|
||
|
+
|
||
|
+void set_encoder_properties(NCompress::NLzma::CEncoder *encoder,
|
||
|
+ lzma_option &opt)
|
||
|
+{
|
||
|
+ /* Almost verbatim from LzmaAlone.cpp. */
|
||
|
+ PROPID propIDs[] =
|
||
|
+ {
|
||
|
+ NCoderPropID::kDictionarySize,
|
||
|
+ NCoderPropID::kPosStateBits,
|
||
|
+ NCoderPropID::kLitContextBits,
|
||
|
+ NCoderPropID::kLitPosBits,
|
||
|
+ NCoderPropID::kAlgorithm,
|
||
|
+ NCoderPropID::kNumFastBytes,
|
||
|
+ NCoderPropID::kMatchFinder,
|
||
|
+ NCoderPropID::kEndMarker
|
||
|
+ };
|
||
|
+ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
|
||
|
+#define VALUE(x) (advanced_options.x >= 0 ? advanced_options.x : opt.x)
|
||
|
+ PROPVARIANT properties[kNumProps];
|
||
|
+ for (int p = 0; p < 6; p++)
|
||
|
+ properties[p].vt = VT_UI4;
|
||
|
+ properties[0].ulVal = UInt32(1 << VALUE (dictionary));
|
||
|
+ properties[1].ulVal = UInt32(VALUE (pos_bits));
|
||
|
+ properties[2].ulVal = UInt32(VALUE (literal_context_bits));
|
||
|
+ properties[3].ulVal = UInt32(VALUE (literal_pos_bits));
|
||
|
+ properties[4].ulVal = UInt32(VALUE (compression_mode));
|
||
|
+ properties[5].ulVal = UInt32(VALUE (fast_bytes));
|
||
|
+#undef VALUE
|
||
|
+
|
||
|
+ properties[6].vt = VT_BSTR;
|
||
|
+ properties[6].bstrVal = (BSTR)opt.match_finder;
|
||
|
+
|
||
|
+ properties[7].vt = VT_BOOL;
|
||
|
+ properties[7].boolVal = stdinput ? VARIANT_TRUE : VARIANT_FALSE;
|
||
|
+
|
||
|
+ if (encoder->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
|
||
|
+ throw Exception("SetCoderProperties() error");
|
||
|
+}
|
||
|
+
|
||
|
+void encode(NCompress::NLzma::CEncoder *encoderSpec,
|
||
|
+ CMyComPtr<ISequentialInStream> inStream,
|
||
|
+ CMyComPtr<ISequentialOutStream> outStream,
|
||
|
+ lzma_option encoder_options,
|
||
|
+ UInt64 fileSize)
|
||
|
+{
|
||
|
+ set_encoder_properties(encoderSpec, encoder_options);
|
||
|
+
|
||
|
+ encoderSpec->WriteCoderProperties(outStream);
|
||
|
+
|
||
|
+ for (int i = 0; i < 8; i++)
|
||
|
+ {
|
||
|
+ Byte b = Byte(fileSize >> (8 * i));
|
||
|
+ if (outStream->Write(&b, sizeof(b), 0) != S_OK)
|
||
|
+ throw Exception("Write error while encoding");
|
||
|
+ }
|
||
|
+
|
||
|
+ HRESULT result = encoderSpec->Code(inStream, outStream, 0, 0, 0);
|
||
|
+
|
||
|
+ if (result == E_OUTOFMEMORY)
|
||
|
+ throw Exception("Cannot allocate memory");
|
||
|
+ else if (result != S_OK) {
|
||
|
+ char buffer[33];
|
||
|
+ snprintf(buffer, 33, "%d", (unsigned int)result);
|
||
|
+ throw Exception(string("Encoder error: ") + buffer);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+void decode(NCompress::NLzma::CDecoder *decoderSpec,
|
||
|
+ CMyComPtr<ISequentialInStream> inStream,
|
||
|
+ CMyComPtr<ISequentialOutStream> outStream)
|
||
|
+{
|
||
|
+ const UInt32 kPropertiesSize = 5;
|
||
|
+ Byte properties[kPropertiesSize];
|
||
|
+ UInt32 processedSize;
|
||
|
+ UInt64 fileSize = 0;
|
||
|
+
|
||
|
+ if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK)
|
||
|
+ throw Exception("Read error");
|
||
|
+ if (processedSize != kPropertiesSize)
|
||
|
+ throw Exception("Read error");
|
||
|
+ if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
|
||
|
+ throw Exception("SetDecoderProperties() error");
|
||
|
+
|
||
|
+ for (int i = 0; i < 8; i++)
|
||
|
+ {
|
||
|
+ Byte b;
|
||
|
+
|
||
|
+ if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK)
|
||
|
+ throw Exception("Read error");
|
||
|
+ if (processedSize != 1)
|
||
|
+ throw Exception("Read error");
|
||
|
+
|
||
|
+ fileSize |= ((UInt64)b) << (8 * i);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (decoderSpec->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
|
||
|
+ throw Exception("Decoder error");
|
||
|
+}
|
||
|
+
|
||
|
+int open_instream(const string infile,
|
||
|
+ CMyComPtr<ISequentialInStream> &inStream,
|
||
|
+ UInt64 &fileSize)
|
||
|
+{
|
||
|
+ CInFileStream *inStreamSpec = new CInFileStream;
|
||
|
+ inStream = inStreamSpec;
|
||
|
+ if (!inStreamSpec->Open(infile.c_str()))
|
||
|
+ throw Exception("Cannot open input file " + infile);
|
||
|
+
|
||
|
+ inStreamSpec->File.GetLength(fileSize);
|
||
|
+
|
||
|
+ return inStreamSpec->File.GetHandle();
|
||
|
+}
|
||
|
+
|
||
|
+int open_outstream(const string outfile,
|
||
|
+ CMyComPtr<ISequentialOutStream> &outStream)
|
||
|
+{
|
||
|
+ COutFileStream *outStreamSpec = new COutFileStream;
|
||
|
+ outStream = outStreamSpec;
|
||
|
+
|
||
|
+ bool open_by_force = (program_mode == PM_TEST) | force;
|
||
|
+
|
||
|
+ if (!outStreamSpec->Create(outfile.c_str(), open_by_force))
|
||
|
+ throw Exception("Cannot open output file " + outfile);
|
||
|
+
|
||
|
+ return outStreamSpec->File.GetHandle();
|
||
|
+}
|
||
|
+
|
||
|
+double get_ratio(int inhandle, int outhandle)
|
||
|
+{
|
||
|
+ struct stat in_stats, out_stats;
|
||
|
+ fstat(inhandle, &in_stats);
|
||
|
+ fstat(outhandle, &out_stats);
|
||
|
+
|
||
|
+ return (double)out_stats.st_size / (double)in_stats.st_size;
|
||
|
+}
|
||
|
+
|
||
|
+mode_t get_file_mode(string filename)
|
||
|
+{
|
||
|
+ struct stat in_stat;
|
||
|
+ lstat(filename.c_str(), &in_stat);
|
||
|
+
|
||
|
+ return in_stat.st_mode;
|
||
|
+}
|
||
|
+
|
||
|
+bool string_ends_with(string str, string ending)
|
||
|
+{
|
||
|
+ return equal(ending.rbegin(), ending.rend(), str.rbegin());
|
||
|
+}
|
||
|
+
|
||
|
+bool extension_is_known(string filename)
|
||
|
+{
|
||
|
+ bool known_format = false;
|
||
|
+ extension_pair extension; int i = 1;
|
||
|
+
|
||
|
+ extension = known_extensions[0];
|
||
|
+ while (extension.from != NULL) {
|
||
|
+ if (string_ends_with(filename, extension.from)) {
|
||
|
+ known_format = true;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ extension = known_extensions[i];
|
||
|
+ i++;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!known_format) {
|
||
|
+ if (!string_ends_with(filename, suffix)) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+string replace_extension(string filename)
|
||
|
+{
|
||
|
+ int suffix_starts_at = filename.length() - strlen (suffix);
|
||
|
+ string from_suffix = filename.substr(suffix_starts_at, strlen (suffix));
|
||
|
+ string ret = filename.substr(0, suffix_starts_at);
|
||
|
+ extension_pair extension; int i = 1;
|
||
|
+
|
||
|
+ bool found_replacement = false;
|
||
|
+ extension = known_extensions[0];
|
||
|
+ while (extension.from != NULL) {
|
||
|
+ if (from_suffix.compare(extension.from) == 0) {
|
||
|
+ ret += extension.to;
|
||
|
+ found_replacement = true;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ extension = known_extensions[i];
|
||
|
+ i++;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+string pretty_print_status(string filename, string output_filename,
|
||
|
+ string ratio)
|
||
|
+{
|
||
|
+ string ret = "";
|
||
|
+
|
||
|
+ ret += filename;
|
||
|
+ ret += ":\t ";
|
||
|
+
|
||
|
+ if (program_mode == PM_TEST) {
|
||
|
+ ret += "decoded succesfully";
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!stdinput && !stdoutput) {
|
||
|
+ ret += ratio;
|
||
|
+ ret += " -- ";
|
||
|
+ }
|
||
|
+
|
||
|
+ if (program_mode == PM_COMPRESS) {
|
||
|
+ if (keep) {
|
||
|
+ ret += "encoded succesfully";
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret += "replaced with ";
|
||
|
+ ret += output_filename;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (program_mode == PM_DECOMPRESS) {
|
||
|
+ if (keep) {
|
||
|
+ ret += "decoded succesfully";
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret += "replaced with ";
|
||
|
+ ret += output_filename;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static string archive_name; // I know, it is crude, but I haven't found any other
|
||
|
+ // way then making a global variable to transfer filename to handler
|
||
|
+
|
||
|
+void signal_handler (int signum)
|
||
|
+{
|
||
|
+ unlink (archive_name.c_str()); // deleting
|
||
|
+ signal (signum, SIG_DFL); // we return the default function to used signal
|
||
|
+ kill (getpid(), signum); // and then send this signal to the process again
|
||
|
+}
|
||
|
+
|
||
|
+} // namespace lzma
|
||
|
+
|
||
|
+
|
||
|
+int main(int argc, char **argv)
|
||
|
+{
|
||
|
+ using namespace lzma;
|
||
|
+ using std::cerr;
|
||
|
+
|
||
|
+ stringVector filenames;
|
||
|
+
|
||
|
+ signal (SIGTERM,signal_handler);
|
||
|
+ signal (SIGHUP,signal_handler);
|
||
|
+ signal (SIGINT,signal_handler);
|
||
|
+
|
||
|
+ try {
|
||
|
+ parse_options(argc, argv, filenames);
|
||
|
+ }
|
||
|
+ catch (...) {
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (program_mode == PM_HELP) {
|
||
|
+ print_help(argv[0]);
|
||
|
+ return STATUS_OK;
|
||
|
+ }
|
||
|
+ else if (program_mode == PM_LICENSE) {
|
||
|
+ print_license();
|
||
|
+ return STATUS_OK;
|
||
|
+ }
|
||
|
+ else if (program_mode == PM_VERSION) {
|
||
|
+ print_version();
|
||
|
+ return STATUS_OK;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (filenames.empty()) {
|
||
|
+ stdinput = true;
|
||
|
+ stdoutput = true;
|
||
|
+
|
||
|
+ /* FIXME: get rid of this */
|
||
|
+ filenames.push_back("-");
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Protection: always create new files with 0600 in order to prevent
|
||
|
+ * outsiders from reading incomplete data. */
|
||
|
+ umask(0077);
|
||
|
+
|
||
|
+ bool warning = false;
|
||
|
+
|
||
|
+ for (int i = 0; i < filenames.size(); i++) {
|
||
|
+ CMyComPtr<ISequentialInStream> inStream;
|
||
|
+ CMyComPtr<ISequentialOutStream> outStream;
|
||
|
+ UInt64 fileSize = 0;
|
||
|
+ int inhandle = 0, outhandle = 0;
|
||
|
+ string output_filename;
|
||
|
+
|
||
|
+ if (stdinput) {
|
||
|
+ inStream = new CStdInFileStream;
|
||
|
+ MY_SET_BINARY_MODE(stdin);
|
||
|
+ fileSize = (UInt64)(Int64)-1;
|
||
|
+
|
||
|
+ inhandle = STDIN_FILENO;
|
||
|
+
|
||
|
+ outStream = new CStdOutFileStream;
|
||
|
+ MY_SET_BINARY_MODE(stdout);
|
||
|
+
|
||
|
+ outhandle = STDOUT_FILENO;
|
||
|
+ }
|
||
|
+ else {
|
||
|
+ mode_t infile_mode = get_file_mode(filenames[i]);
|
||
|
+ if (!S_ISREG(infile_mode)) {
|
||
|
+ if (S_ISDIR(infile_mode)) {
|
||
|
+ warning = true;
|
||
|
+ cerr << argv[0] << ": " << filenames[i] << ": "
|
||
|
+ << "cowardly refusing to work on directory"
|
||
|
+ << endl;
|
||
|
+
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ else if (S_ISLNK(infile_mode)) {
|
||
|
+ if (!stdoutput && !force) {
|
||
|
+ warning = true;
|
||
|
+
|
||
|
+ cerr << argv[0] << ": " << filenames[i] << ": "
|
||
|
+ << "cowardly refusing to work on symbolic link "
|
||
|
+ << "(use --force to force encoding or decoding)"
|
||
|
+ << endl;
|
||
|
+
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else {
|
||
|
+ warning = true;
|
||
|
+
|
||
|
+ cerr << argv[0] << ": " << filenames[i] << ": "
|
||
|
+ << "doesn't exist or is not a regular file"
|
||
|
+ << endl;
|
||
|
+
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ // Test if the file already ends with *suffix.
|
||
|
+ if (program_mode == PM_COMPRESS && !force
|
||
|
+ && string_ends_with(filenames[i],
|
||
|
+ suffix)) {
|
||
|
+ warning = true;
|
||
|
+
|
||
|
+ cerr << filenames[i] << " already has "
|
||
|
+ << suffix << " suffix -- unchanged\n";
|
||
|
+
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Test if the file extension is known.
|
||
|
+ if (program_mode == PM_DECOMPRESS
|
||
|
+ && !extension_is_known(filenames[i])) {
|
||
|
+ warning = true;
|
||
|
+
|
||
|
+ cerr << filenames[i] << ": "
|
||
|
+ << " unknown suffix -- unchanged"
|
||
|
+ << endl;
|
||
|
+
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ try {
|
||
|
+ inhandle = open_instream(filenames[i], inStream, fileSize);
|
||
|
+ }
|
||
|
+ catch (Exception e) {
|
||
|
+ cerr << argv[0] << ": " << e.what() << endl;
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (stdoutput) {
|
||
|
+ outStream = new CStdOutFileStream;
|
||
|
+ MY_SET_BINARY_MODE(stdout);
|
||
|
+
|
||
|
+ outhandle = STDOUT_FILENO;
|
||
|
+ }
|
||
|
+ else {
|
||
|
+ /* Testing mode is nothing else but decoding
|
||
|
+ * and throwing away the result. */
|
||
|
+ if (program_mode == PM_TEST)
|
||
|
+ output_filename = "/dev/null";
|
||
|
+ else if (program_mode == PM_DECOMPRESS)
|
||
|
+ output_filename = replace_extension(filenames[i]);
|
||
|
+ else
|
||
|
+ output_filename = filenames[i]
|
||
|
+ + suffix;
|
||
|
+ archive_name = output_filename;
|
||
|
+
|
||
|
+ try {
|
||
|
+ outhandle = open_outstream(output_filename, outStream);
|
||
|
+ }
|
||
|
+ catch (Exception e) {
|
||
|
+ cerr << argv[0] << ": " << e.what() << endl;
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ // Unless --force is specified, do not read/write compressed
|
||
|
+ // data from/to a terminal.
|
||
|
+ if (!force) {
|
||
|
+ if (program_mode == PM_COMPRESS && isatty(outhandle)) {
|
||
|
+ cerr << argv[0] << ": compressed data not "
|
||
|
+ "written to a terminal. Use "
|
||
|
+ "-f to force compression.\n"
|
||
|
+ << argv[0] << ": For help, type: "
|
||
|
+ << argv[0] << " -h\n";
|
||
|
+ return STATUS_ERROR;
|
||
|
+ } else if (program_mode == PM_DECOMPRESS
|
||
|
+ && isatty(inhandle)) {
|
||
|
+ cerr << argv[0] << ": compressed data not "
|
||
|
+ "read from a terminal. Use "
|
||
|
+ "-f to force decompression.\n"
|
||
|
+ << argv[0] << ": For help, type: "
|
||
|
+ << argv[0] << " -h\n";
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (program_mode == PM_COMPRESS) {
|
||
|
+ NCompress::NLzma::CEncoder *encoderSpec =
|
||
|
+ new NCompress::NLzma::CEncoder;
|
||
|
+
|
||
|
+ lzma_option options = option_mapping[compression_mode];
|
||
|
+
|
||
|
+ try {
|
||
|
+ encode(encoderSpec, inStream, outStream, options, fileSize);
|
||
|
+ }
|
||
|
+ catch (Exception e) {
|
||
|
+ cerr << argv[0] << ": " << e.what() << endl;
|
||
|
+ unlink(output_filename.c_str());
|
||
|
+ delete(encoderSpec);
|
||
|
+
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ delete(encoderSpec);
|
||
|
+ }
|
||
|
+ else { // PM_DECOMPRESS | PM_TEST
|
||
|
+ NCompress::NLzma::CDecoder *decoderSpec =
|
||
|
+ new NCompress::NLzma::CDecoder;
|
||
|
+
|
||
|
+ try {
|
||
|
+ decode(decoderSpec, inStream, outStream);
|
||
|
+ }
|
||
|
+ catch (Exception e) {
|
||
|
+ cerr << argv[0] << ": " << e.what() << endl;
|
||
|
+ unlink(output_filename.c_str());
|
||
|
+ delete(decoderSpec);
|
||
|
+
|
||
|
+ return STATUS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ delete(decoderSpec);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Set permissions and owners. */
|
||
|
+ if ( (program_mode == PM_COMPRESS || program_mode == PM_DECOMPRESS )
|
||
|
+ && (!stdinput && !stdoutput) ) {
|
||
|
+
|
||
|
+ int ret = 0;
|
||
|
+ struct stat file_stats;
|
||
|
+ ret = fstat(inhandle, &file_stats);
|
||
|
+
|
||
|
+ ret = fchmod(outhandle, file_stats.st_mode);
|
||
|
+ ret = fchown(outhandle, file_stats.st_uid, file_stats.st_gid);
|
||
|
+ // We need to call fchmod() again, since otherwise the SUID bits
|
||
|
+ // are lost.
|
||
|
+ ret = fchmod(outhandle, file_stats.st_mode);
|
||
|
+
|
||
|
+ struct timeval file_times[2];
|
||
|
+ // Access time
|
||
|
+ file_times[0].tv_sec = file_stats.st_atime;
|
||
|
+ file_times[0].tv_usec = 0;
|
||
|
+ // Modification time
|
||
|
+ file_times[1].tv_sec = file_stats.st_mtime;
|
||
|
+ file_times[1].tv_usec = 0;
|
||
|
+
|
||
|
+ ret = futimes(outhandle, file_times);
|
||
|
+
|
||
|
+ if (!keep)
|
||
|
+ unlink(filenames[i].c_str());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (verbosity > 0) {
|
||
|
+ if (stdoutput) {
|
||
|
+ cerr << filenames[i] << ":\t ";
|
||
|
+ cerr << "decoded succesfully"
|
||
|
+ << endl;
|
||
|
+ }
|
||
|
+
|
||
|
+ else {
|
||
|
+ char buf[10] = { 0 };
|
||
|
+
|
||
|
+ if (program_mode == PM_DECOMPRESS)
|
||
|
+ snprintf(buf, 10, "%.2f%%",
|
||
|
+ (1 - get_ratio(outhandle, inhandle)) * 100);
|
||
|
+ if (program_mode == PM_COMPRESS)
|
||
|
+ snprintf(buf, 10, "%.2f%%",
|
||
|
+ (1 - get_ratio(inhandle, outhandle)) * 100);
|
||
|
+
|
||
|
+ string ratio = buf;
|
||
|
+ cerr << pretty_print_status(filenames[i], output_filename,
|
||
|
+ ratio)
|
||
|
+ << endl;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (warning)
|
||
|
+ return STATUS_WARNING;
|
||
|
+
|
||
|
+ return STATUS_OK;
|
||
|
+}
|
||
|
+
|
||
|
Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/Exception.h
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/Exception.h 2009-06-01 22:01:10.000000000 +0200
|
||
|
@@ -0,0 +1,45 @@
|
||
|
+/* A couple of exceptions for lzmp.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2005 Ville Koskinen
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or
|
||
|
+ * modify it under the terms of the GNU General Public License
|
||
|
+ * as published by the Free Software Foundation; either version 2
|
||
|
+ * 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 General Public License for more details.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef _EXCEPTION_H_
|
||
|
+#define _EXCEPTION_H_
|
||
|
+
|
||
|
+#include <string>
|
||
|
+using std::string;
|
||
|
+
|
||
|
+class Exception
|
||
|
+{
|
||
|
+private:
|
||
|
+ string message;
|
||
|
+public:
|
||
|
+ Exception(char *what): message(what) { }
|
||
|
+ Exception(string what): message(what) { }
|
||
|
+
|
||
|
+ ~Exception() { }
|
||
|
+
|
||
|
+ string what(void) { return message; }
|
||
|
+};
|
||
|
+
|
||
|
+class ArgumentException: public Exception
|
||
|
+{
|
||
|
+public:
|
||
|
+ ArgumentException(char *what): Exception(what) { }
|
||
|
+ ArgumentException(string what): Exception(what) { }
|
||
|
+
|
||
|
+ ~ArgumentException() { }
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
|
||
|
===================================================================
|
||
|
--- lzma-4.65.orig/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-06-01 22:00:54.000000000 +0200
|
||
|
+++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-06-01 22:06:13.000000000 +0200
|
||
|
@@ -1,9 +1,10 @@
|
||
|
-PROG = lzma
|
||
|
+PROG = lzma_alone
|
||
|
+PROG2 = lzma
|
||
|
CXX = g++ -O2 -Wall
|
||
|
CXX_C = gcc -O2 -Wall
|
||
|
LIB = -lm
|
||
|
RM = rm -f
|
||
|
-CFLAGS = -c -D_FILE_OFFSET_BITS=64
|
||
|
+CFLAGS = -c -I ../../../ -D_FILE_OFFSET_BITS=64 -DPACKAGE_VERSION="\"4.32.0beta3\""
|
||
|
|
||
|
ifdef SystemDrive
|
||
|
IS_MINGW = 1
|
||
|
@@ -45,12 +46,35 @@
|
||
|
Lzma86Dec.o \
|
||
|
Lzma86Enc.o \
|
||
|
|
||
|
+OBJS2 = \
|
||
|
+ C_FileIO.o \
|
||
|
+ CRC.o \
|
||
|
+ Alloc.o \
|
||
|
+ FileStreams.o \
|
||
|
+ StreamUtils.o \
|
||
|
+ InBuffer.o \
|
||
|
+ OutBuffer.o \
|
||
|
+ LzmaDecoder.o \
|
||
|
+ StringConvert.o \
|
||
|
+ StringToInt.o \
|
||
|
+ LzmaEncoder.o \
|
||
|
+ LzmaDec.o \
|
||
|
+ LzmaEnc.o \
|
||
|
+ LzFind.o \
|
||
|
+ 7zCrc.o \
|
||
|
+ lzmp.o
|
||
|
|
||
|
-all: $(PROG)
|
||
|
+all: $(PROG) $(PROG2)
|
||
|
|
||
|
$(PROG): $(OBJS)
|
||
|
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
|
||
|
|
||
|
+$(PROG2): $(OBJS2)
|
||
|
+ $(CXX) -o $(PROG2) $(LDFLAGS) $(OBJS2) $(LIB)
|
||
|
+
|
||
|
+lzmp.o: lzmp.cpp
|
||
|
+ $(CXX) $(CFLAGS) lzmp.cpp
|
||
|
+
|
||
|
LzmaAlone.o: LzmaAlone.cpp
|
||
|
$(CXX) $(CFLAGS) LzmaAlone.cpp
|
||
|
|
||
|
@@ -131,5 +153,5 @@
|
||
|
$(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c
|
||
|
|
||
|
clean:
|
||
|
- -$(RM) $(PROG) $(OBJS)
|
||
|
+ -$(RM) $(PROG) $(PROG2) $(OBJS)
|
||
|
|
||
|
Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzma_version.h
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzma_version.h 2009-06-01 22:01:10.000000000 +0200
|
||
|
@@ -0,0 +1,31 @@
|
||
|
+#ifndef LZMA_VERSION_H
|
||
|
+#define LZMA_VERSION_H
|
||
|
+
|
||
|
+/*
|
||
|
+ Version and copyright information used by LZMA utils.
|
||
|
+*/
|
||
|
+
|
||
|
+static const char *LZMA_SDK_VERSION_STRING = "4.43";
|
||
|
+
|
||
|
+static const char *LZMA_SDK_COPYRIGHT_STRING =
|
||
|
+ "Copyright (C) 1999-2006 Igor Pavlov";
|
||
|
+
|
||
|
+static const char *LZMA_SDK_COPYRIGHT_INFO =
|
||
|
+ " See http://7-zip.org/sdk.html or the documentation of LZMA SDK for\n"
|
||
|
+ " the license. For reference, the version 4.43 is free software\n"
|
||
|
+ " licensed under the GNU LGPL.";
|
||
|
+
|
||
|
+
|
||
|
+static const char *LZMA_UTILS_VERSION_STRING = PACKAGE_VERSION;
|
||
|
+
|
||
|
+static const char *LZMA_UTILS_COPYRIGHT_STRING =
|
||
|
+ "Copyright (C) 2006 Lasse Collin";
|
||
|
+
|
||
|
+static const char *LZMA_UTILS_COPYRIGHT_INFO =
|
||
|
+ "This program comes with ABSOLUTELY NO WARRANTY.\n"
|
||
|
+ "You may redistribute copies of this program\n"
|
||
|
+ "under the terms of the GNU General Public License.\n"
|
||
|
+ "For more information about these matters, see the file "
|
||
|
+ "named COPYING.\n";
|
||
|
+
|
||
|
+#endif /* ifndef LZMA_VERSION_H */
|
||
|
Index: lzma-4.65/CPP/Common/C_FileIO.h
|
||
|
===================================================================
|
||
|
--- lzma-4.65.orig/CPP/Common/C_FileIO.h 2009-05-15 23:33:51.000000000 +0200
|
||
|
+++ lzma-4.65/CPP/Common/C_FileIO.h 2009-06-01 22:06:56.000000000 +0200
|
||
|
@@ -24,6 +24,7 @@
|
||
|
bool Close();
|
||
|
bool GetLength(UInt64 &length) const;
|
||
|
off_t Seek(off_t distanceToMove, int moveMethod) const;
|
||
|
+ int GetHandle() const { return _handle; }
|
||
|
};
|
||
|
|
||
|
class CInFile: public CFileBase
|