2007-12-08 23:42:33 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
/// \file args.c
|
|
|
|
/// \brief Argument parsing
|
|
|
|
///
|
|
|
|
/// \note Filter-specific options parsing is in options.c.
|
|
|
|
//
|
2009-04-13 10:27:40 +02:00
|
|
|
// Author: Lasse Collin
|
2007-12-08 23:42:33 +01:00
|
|
|
//
|
2009-04-13 10:27:40 +02:00
|
|
|
// This file has been put into the public domain.
|
|
|
|
// You can do whatever you want with this file.
|
2007-12-08 23:42:33 +01:00
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "private.h"
|
|
|
|
|
|
|
|
#include "getopt.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
|
|
bool opt_stdout = false;
|
|
|
|
bool opt_force = false;
|
|
|
|
bool opt_keep_original = false;
|
|
|
|
|
|
|
|
// We don't modify or free() this, but we need to assign it in some
|
|
|
|
// non-const pointers.
|
|
|
|
const char *stdin_filename = "(stdin)";
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2008-11-19 19:46:52 +01:00
|
|
|
parse_real(args_info *args, int argc, char **argv)
|
2007-12-08 23:42:33 +01:00
|
|
|
{
|
2008-11-19 19:46:52 +01:00
|
|
|
enum {
|
|
|
|
OPT_SUBBLOCK = INT_MIN,
|
|
|
|
OPT_X86,
|
|
|
|
OPT_POWERPC,
|
|
|
|
OPT_IA64,
|
|
|
|
OPT_ARM,
|
|
|
|
OPT_ARMTHUMB,
|
|
|
|
OPT_SPARC,
|
|
|
|
OPT_DELTA,
|
|
|
|
OPT_LZMA1,
|
|
|
|
OPT_LZMA2,
|
|
|
|
|
|
|
|
OPT_FILES,
|
|
|
|
OPT_FILES0,
|
|
|
|
};
|
|
|
|
|
2009-05-22 13:43:00 +02:00
|
|
|
static const char short_opts[]
|
|
|
|
= "cC:defF:hHlkM:qQrS:tT:vVz0123456789";
|
2008-11-19 19:46:52 +01:00
|
|
|
|
|
|
|
static const struct option long_opts[] = {
|
|
|
|
// Operation mode
|
|
|
|
{ "compress", no_argument, NULL, 'z' },
|
|
|
|
{ "decompress", no_argument, NULL, 'd' },
|
|
|
|
{ "uncompress", no_argument, NULL, 'd' },
|
|
|
|
{ "test", no_argument, NULL, 't' },
|
|
|
|
{ "list", no_argument, NULL, 'l' },
|
|
|
|
|
|
|
|
// Operation modifiers
|
|
|
|
{ "keep", no_argument, NULL, 'k' },
|
|
|
|
{ "force", no_argument, NULL, 'f' },
|
|
|
|
{ "stdout", no_argument, NULL, 'c' },
|
|
|
|
{ "to-stdout", no_argument, NULL, 'c' },
|
|
|
|
{ "suffix", required_argument, NULL, 'S' },
|
|
|
|
// { "recursive", no_argument, NULL, 'r' }, // TODO
|
|
|
|
{ "files", optional_argument, NULL, OPT_FILES },
|
|
|
|
{ "files0", optional_argument, NULL, OPT_FILES0 },
|
|
|
|
|
|
|
|
// Basic compression settings
|
|
|
|
{ "format", required_argument, NULL, 'F' },
|
|
|
|
{ "check", required_argument, NULL, 'C' },
|
|
|
|
{ "memory", required_argument, NULL, 'M' },
|
|
|
|
{ "threads", required_argument, NULL, 'T' },
|
|
|
|
|
2008-12-27 18:30:19 +01:00
|
|
|
{ "extreme", no_argument, NULL, 'e' },
|
|
|
|
{ "fast", no_argument, NULL, '0' },
|
2008-11-19 19:46:52 +01:00
|
|
|
{ "best", no_argument, NULL, '9' },
|
|
|
|
|
|
|
|
// Filters
|
|
|
|
{ "lzma1", optional_argument, NULL, OPT_LZMA1 },
|
|
|
|
{ "lzma2", optional_argument, NULL, OPT_LZMA2 },
|
2009-05-23 14:12:23 +02:00
|
|
|
{ "x86", optional_argument, NULL, OPT_X86 },
|
|
|
|
{ "powerpc", optional_argument, NULL, OPT_POWERPC },
|
|
|
|
{ "ia64", optional_argument, NULL, OPT_IA64 },
|
|
|
|
{ "arm", optional_argument, NULL, OPT_ARM },
|
|
|
|
{ "armthumb", optional_argument, NULL, OPT_ARMTHUMB },
|
|
|
|
{ "sparc", optional_argument, NULL, OPT_SPARC },
|
2008-11-19 19:46:52 +01:00
|
|
|
{ "delta", optional_argument, NULL, OPT_DELTA },
|
|
|
|
{ "subblock", optional_argument, NULL, OPT_SUBBLOCK },
|
|
|
|
|
|
|
|
// Other options
|
|
|
|
{ "quiet", no_argument, NULL, 'q' },
|
|
|
|
{ "verbose", no_argument, NULL, 'v' },
|
2009-05-22 13:43:00 +02:00
|
|
|
{ "no-warn", no_argument, NULL, 'Q' },
|
2008-11-19 19:46:52 +01:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "long-help", no_argument, NULL, 'H' },
|
|
|
|
{ "version", no_argument, NULL, 'V' },
|
|
|
|
|
|
|
|
{ NULL, 0, NULL, 0 }
|
|
|
|
};
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL))
|
|
|
|
!= -1) {
|
|
|
|
switch (c) {
|
2008-12-27 18:30:19 +01:00
|
|
|
// Compression preset (also for decompression if --format=raw)
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
2007-12-08 23:42:33 +01:00
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_set_preset(c - '0');
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// --memory
|
2009-05-22 10:29:50 +02:00
|
|
|
case 'M': {
|
|
|
|
// Support specifying the limit as a percentage of
|
|
|
|
// installed physical RAM.
|
|
|
|
size_t len = strlen(optarg);
|
|
|
|
if (len > 0 && optarg[len - 1] == '%') {
|
|
|
|
optarg[len - 1] = '\0';
|
|
|
|
hardware_memlimit_set_percentage(
|
|
|
|
str_to_uint64(
|
|
|
|
"memory%", optarg, 1, 100));
|
|
|
|
} else {
|
|
|
|
// On 32-bit systems, SIZE_MAX would make more
|
|
|
|
// sense than UINT64_MAX. But use UINT64_MAX
|
|
|
|
// still so that scripts that assume > 4 GiB
|
|
|
|
// values don't break.
|
|
|
|
hardware_memlimit_set(str_to_uint64(
|
|
|
|
"memory", optarg,
|
|
|
|
0, UINT64_MAX));
|
|
|
|
}
|
|
|
|
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
2009-05-22 10:29:50 +02:00
|
|
|
}
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// --suffix
|
|
|
|
case 'S':
|
2008-11-19 19:46:52 +01:00
|
|
|
suffix_set(optarg);
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'T':
|
2009-02-13 23:45:29 +01:00
|
|
|
hardware_threadlimit_set(str_to_uint64(
|
2009-05-22 10:29:50 +02:00
|
|
|
"threads", optarg, 0, UINT32_MAX));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
// --version
|
|
|
|
case 'V':
|
|
|
|
// This doesn't return.
|
2008-11-19 19:46:52 +01:00
|
|
|
message_version();
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// --stdout
|
|
|
|
case 'c':
|
|
|
|
opt_stdout = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --decompress
|
|
|
|
case 'd':
|
|
|
|
opt_mode = MODE_DECOMPRESS;
|
|
|
|
break;
|
|
|
|
|
2008-12-27 18:30:19 +01:00
|
|
|
// --extreme
|
|
|
|
case 'e':
|
|
|
|
coder_set_extreme();
|
|
|
|
break;
|
|
|
|
|
2007-12-08 23:42:33 +01:00
|
|
|
// --force
|
|
|
|
case 'f':
|
|
|
|
opt_force = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --help
|
|
|
|
case 'h':
|
|
|
|
// This doesn't return.
|
2008-11-19 19:46:52 +01:00
|
|
|
message_help(false);
|
|
|
|
|
|
|
|
// --long-help
|
|
|
|
case 'H':
|
|
|
|
// This doesn't return.
|
|
|
|
message_help(true);
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// --list
|
|
|
|
case 'l':
|
|
|
|
opt_mode = MODE_LIST;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --keep
|
|
|
|
case 'k':
|
|
|
|
opt_keep_original = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --quiet
|
|
|
|
case 'q':
|
2008-11-19 19:46:52 +01:00
|
|
|
message_verbosity_decrease();
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
2009-05-22 13:43:00 +02:00
|
|
|
case 'Q':
|
|
|
|
set_exit_no_warn();
|
|
|
|
break;
|
|
|
|
|
2007-12-08 23:42:33 +01:00
|
|
|
case 't':
|
|
|
|
opt_mode = MODE_TEST;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// --verbose
|
|
|
|
case 'v':
|
2008-11-19 19:46:52 +01:00
|
|
|
message_verbosity_increase();
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'z':
|
|
|
|
opt_mode = MODE_COMPRESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Filter setup
|
|
|
|
|
|
|
|
case OPT_SUBBLOCK:
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_add_filter(LZMA_FILTER_SUBBLOCK,
|
|
|
|
options_subblock(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_X86:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_X86,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_POWERPC:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_POWERPC,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_IA64:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_IA64,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_ARM:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_ARM,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_ARMTHUMB:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_ARMTHUMB,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_SPARC:
|
2009-05-23 14:12:23 +02:00
|
|
|
coder_add_filter(LZMA_FILTER_SPARC,
|
|
|
|
options_bcj(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_DELTA:
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_add_filter(LZMA_FILTER_DELTA,
|
|
|
|
options_delta(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
2008-09-04 10:53:06 +02:00
|
|
|
case OPT_LZMA1:
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_add_filter(LZMA_FILTER_LZMA1,
|
|
|
|
options_lzma(optarg));
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
|
2008-08-28 21:53:15 +02:00
|
|
|
case OPT_LZMA2:
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_add_filter(LZMA_FILTER_LZMA2,
|
|
|
|
options_lzma(optarg));
|
2008-08-28 21:53:15 +02:00
|
|
|
break;
|
|
|
|
|
2007-12-08 23:42:33 +01:00
|
|
|
// Other
|
|
|
|
|
|
|
|
// --format
|
|
|
|
case 'F': {
|
2008-10-02 21:51:46 +02:00
|
|
|
// Just in case, support both "lzma" and "alone" since
|
|
|
|
// the latter was used for forward compatibility in
|
|
|
|
// LZMA Utils 4.32.x.
|
|
|
|
static const struct {
|
|
|
|
char str[8];
|
|
|
|
enum format_type format;
|
|
|
|
} types[] = {
|
|
|
|
{ "auto", FORMAT_AUTO },
|
|
|
|
{ "xz", FORMAT_XZ },
|
|
|
|
{ "lzma", FORMAT_LZMA },
|
|
|
|
{ "alone", FORMAT_LZMA },
|
|
|
|
// { "gzip", FORMAT_GZIP },
|
|
|
|
// { "gz", FORMAT_GZIP },
|
|
|
|
{ "raw", FORMAT_RAW },
|
2007-12-08 23:42:33 +01:00
|
|
|
};
|
|
|
|
|
2008-10-02 21:51:46 +02:00
|
|
|
size_t i = 0;
|
2008-11-19 19:46:52 +01:00
|
|
|
while (strcmp(types[i].str, optarg) != 0)
|
|
|
|
if (++i == ARRAY_SIZE(types))
|
|
|
|
message_fatal(_("%s: Unknown file "
|
2007-12-08 23:42:33 +01:00
|
|
|
"format type"),
|
|
|
|
optarg);
|
|
|
|
|
2008-10-02 21:51:46 +02:00
|
|
|
opt_format = types[i].format;
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// --check
|
|
|
|
case 'C': {
|
|
|
|
static const struct {
|
2008-10-02 21:51:46 +02:00
|
|
|
char str[8];
|
|
|
|
lzma_check check;
|
2007-12-08 23:42:33 +01:00
|
|
|
} types[] = {
|
|
|
|
{ "none", LZMA_CHECK_NONE },
|
|
|
|
{ "crc32", LZMA_CHECK_CRC32 },
|
|
|
|
{ "crc64", LZMA_CHECK_CRC64 },
|
|
|
|
{ "sha256", LZMA_CHECK_SHA256 },
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
while (strcmp(types[i].str, optarg) != 0) {
|
2008-11-19 19:46:52 +01:00
|
|
|
if (++i == ARRAY_SIZE(types))
|
2009-02-13 16:30:30 +01:00
|
|
|
message_fatal(_("%s: Unsupported "
|
|
|
|
"integrity "
|
2008-11-19 19:46:52 +01:00
|
|
|
"check type"), optarg);
|
2007-12-08 23:42:33 +01:00
|
|
|
}
|
|
|
|
|
2009-02-13 16:30:30 +01:00
|
|
|
// Use a separate check in case we are using different
|
|
|
|
// liblzma than what was used to compile us.
|
|
|
|
if (!lzma_check_is_supported(types[i].check))
|
|
|
|
message_fatal(_("%s: Unsupported integrity "
|
|
|
|
"check type"), optarg);
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_set_check(types[i].check);
|
2007-12-08 23:42:33 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case OPT_FILES:
|
2008-11-19 19:46:52 +01:00
|
|
|
args->files_delim = '\n';
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// Fall through
|
|
|
|
|
|
|
|
case OPT_FILES0:
|
2008-11-19 19:46:52 +01:00
|
|
|
if (args->files_name != NULL)
|
|
|
|
message_fatal(_("Only one file can be "
|
2007-12-08 23:42:33 +01:00
|
|
|
"specified with `--files'"
|
|
|
|
"or `--files0'."));
|
|
|
|
|
|
|
|
if (optarg == NULL) {
|
2008-11-19 19:46:52 +01:00
|
|
|
args->files_name = (char *)stdin_filename;
|
|
|
|
args->files_file = stdin;
|
2007-12-08 23:42:33 +01:00
|
|
|
} else {
|
2008-11-19 19:46:52 +01:00
|
|
|
args->files_name = optarg;
|
|
|
|
args->files_file = fopen(optarg,
|
2007-12-08 23:42:33 +01:00
|
|
|
c == OPT_FILES ? "r" : "rb");
|
2008-11-19 19:46:52 +01:00
|
|
|
if (args->files_file == NULL)
|
|
|
|
message_fatal("%s: %s", optarg,
|
2007-12-08 23:42:33 +01:00
|
|
|
strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2008-11-19 19:46:52 +01:00
|
|
|
message_try_help();
|
|
|
|
my_exit(E_ERROR);
|
2007-12-08 23:42:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2008-11-19 19:46:52 +01:00
|
|
|
parse_environment(args_info *args, char *argv0)
|
2007-12-08 23:42:33 +01:00
|
|
|
{
|
2008-11-19 19:46:52 +01:00
|
|
|
char *env = getenv("XZ_OPT");
|
2007-12-08 23:42:33 +01:00
|
|
|
if (env == NULL)
|
|
|
|
return;
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// We modify the string, so make a copy of it.
|
2007-12-08 23:42:33 +01:00
|
|
|
env = xstrdup(env);
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Calculate the number of arguments in env. argc stats at one
|
|
|
|
// to include space for the program name.
|
|
|
|
int argc = 1;
|
2007-12-08 23:42:33 +01:00
|
|
|
bool prev_was_space = true;
|
|
|
|
for (size_t i = 0; env[i] != '\0'; ++i) {
|
2009-06-24 12:01:59 +02:00
|
|
|
// NOTE: Cast to unsigned char is needed so that correct
|
|
|
|
// value gets passed to isspace(), which expects
|
|
|
|
// unsigned char cast to int. Casting to int is done
|
|
|
|
// automatically due to integer promotion, but we need to
|
|
|
|
// force char to unsigned char manually. Otherwise 8-bit
|
|
|
|
// characters would get promoted to wrong value if
|
|
|
|
// char is signed.
|
|
|
|
if (isspace((unsigned char)env[i])) {
|
2007-12-08 23:42:33 +01:00
|
|
|
prev_was_space = true;
|
|
|
|
} else if (prev_was_space) {
|
|
|
|
prev_was_space = false;
|
2008-11-19 19:46:52 +01:00
|
|
|
|
|
|
|
// Keep argc small enough to fit into a singed int
|
|
|
|
// and to keep it usable for memory allocation.
|
|
|
|
if (++argc == MIN(INT_MAX, SIZE_MAX / sizeof(char *)))
|
|
|
|
message_fatal(_("The environment variable "
|
|
|
|
"XZ_OPT contains too many "
|
2007-12-08 23:42:33 +01:00
|
|
|
"arguments"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Allocate memory to hold pointers to the arguments. Add one to get
|
|
|
|
// space for the terminating NULL (if some systems happen to need it).
|
|
|
|
char **argv = xmalloc(((size_t)(argc) + 1) * sizeof(char *));
|
2007-12-08 23:42:33 +01:00
|
|
|
argv[0] = argv0;
|
|
|
|
argv[argc] = NULL;
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Go through the string again. Split the arguments using '\0'
|
|
|
|
// characters and add pointers to the resulting strings to argv.
|
2007-12-08 23:42:33 +01:00
|
|
|
argc = 1;
|
|
|
|
prev_was_space = true;
|
|
|
|
for (size_t i = 0; env[i] != '\0'; ++i) {
|
2009-06-24 12:01:59 +02:00
|
|
|
if (isspace((unsigned char)env[i])) {
|
2007-12-08 23:42:33 +01:00
|
|
|
prev_was_space = true;
|
2008-11-19 19:46:52 +01:00
|
|
|
env[i] = '\0';
|
2007-12-08 23:42:33 +01:00
|
|
|
} else if (prev_was_space) {
|
|
|
|
prev_was_space = false;
|
|
|
|
argv[argc++] = env + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Parse the argument list we got from the environment. All non-option
|
|
|
|
// arguments i.e. filenames are ignored.
|
|
|
|
parse_real(args, argc, argv);
|
2007-12-08 23:42:33 +01:00
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Reset the state of the getopt_long() so that we can parse the
|
|
|
|
// command line options too. There are two incompatible ways to
|
|
|
|
// do it.
|
|
|
|
#ifdef HAVE_OPTRESET
|
|
|
|
// BSD
|
|
|
|
optind = 1;
|
|
|
|
optreset = 1;
|
|
|
|
#else
|
|
|
|
// GNU, Solaris
|
|
|
|
optind = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// We don't need the argument list from environment anymore.
|
|
|
|
free(argv);
|
2007-12-08 23:42:33 +01:00
|
|
|
free(env);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
extern void
|
|
|
|
args_parse(args_info *args, int argc, char **argv)
|
2007-12-08 23:42:33 +01:00
|
|
|
{
|
2008-11-19 19:46:52 +01:00
|
|
|
// Initialize those parts of *args that we need later.
|
|
|
|
args->files_name = NULL;
|
|
|
|
args->files_file = NULL;
|
|
|
|
args->files_delim = '\0';
|
2008-10-02 21:51:46 +02:00
|
|
|
|
2007-12-08 23:42:33 +01:00
|
|
|
// Check how we were called.
|
|
|
|
{
|
2009-02-13 16:29:02 +01:00
|
|
|
#ifdef DOSLIKE
|
|
|
|
// We adjusted argv[0] in the beginning of main() so we don't
|
|
|
|
// need to do anything here.
|
|
|
|
const char *name = argv[0];
|
2009-02-08 09:37:50 +01:00
|
|
|
#else
|
2009-02-13 16:29:02 +01:00
|
|
|
// Remove the leading path name, if any.
|
2008-11-19 19:46:52 +01:00
|
|
|
const char *name = strrchr(argv[0], '/');
|
|
|
|
if (name == NULL)
|
|
|
|
name = argv[0];
|
|
|
|
else
|
|
|
|
++name;
|
2009-02-08 09:37:50 +01:00
|
|
|
#endif
|
2008-11-19 19:46:52 +01:00
|
|
|
|
|
|
|
// NOTE: It's possible that name[0] is now '\0' if argv[0]
|
|
|
|
// is weird, but it doesn't matter here.
|
|
|
|
|
2009-05-22 11:27:43 +02:00
|
|
|
// If the command name contains "lz",
|
|
|
|
// it implies --format=lzma.
|
2008-11-19 19:46:52 +01:00
|
|
|
if (strstr(name, "lz") != NULL)
|
2009-05-22 11:27:43 +02:00
|
|
|
opt_format = FORMAT_LZMA;
|
2008-11-19 19:46:52 +01:00
|
|
|
|
|
|
|
// Operation mode
|
|
|
|
if (strstr(name, "cat") != NULL) {
|
|
|
|
// Imply --decompress --stdout
|
|
|
|
opt_mode = MODE_DECOMPRESS;
|
|
|
|
opt_stdout = true;
|
|
|
|
} else if (strstr(name, "un") != NULL) {
|
|
|
|
// Imply --decompress
|
|
|
|
opt_mode = MODE_DECOMPRESS;
|
2007-12-08 23:42:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// First the flags from environment
|
2008-11-19 19:46:52 +01:00
|
|
|
parse_environment(args, argv[0]);
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// Then from the command line
|
|
|
|
optind = 1;
|
2008-11-19 19:46:52 +01:00
|
|
|
parse_real(args, argc, argv);
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// Never remove the source file when the destination is not on disk.
|
|
|
|
// In test mode the data is written nowhere, but setting opt_stdout
|
|
|
|
// will make the rest of the code behave well.
|
|
|
|
if (opt_stdout || opt_mode == MODE_TEST) {
|
|
|
|
opt_keep_original = true;
|
|
|
|
opt_stdout = true;
|
|
|
|
}
|
|
|
|
|
2009-05-22 11:27:43 +02:00
|
|
|
// When compressing, if no --format flag was used, or it
|
|
|
|
// was --format=auto, we compress to the .xz format.
|
2008-10-02 21:51:46 +02:00
|
|
|
if (opt_mode == MODE_COMPRESS && opt_format == FORMAT_AUTO)
|
2009-05-22 11:27:43 +02:00
|
|
|
opt_format = FORMAT_XZ;
|
2008-10-02 21:51:46 +02:00
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
// Compression settings need to be validated (options themselves and
|
|
|
|
// their memory usage) when compressing to any file format. It has to
|
|
|
|
// be done also when uncompressing raw data, since for raw decoding
|
|
|
|
// the options given on the command line are used to know what kind
|
|
|
|
// of raw data we are supposed to decode.
|
2008-10-02 21:51:46 +02:00
|
|
|
if (opt_mode == MODE_COMPRESS || opt_format == FORMAT_RAW)
|
2008-11-19 19:46:52 +01:00
|
|
|
coder_set_compression_settings();
|
2007-12-08 23:42:33 +01:00
|
|
|
|
|
|
|
// If no filenames are given, use stdin.
|
2008-11-19 19:46:52 +01:00
|
|
|
if (argv[optind] == NULL && args->files_name == NULL) {
|
|
|
|
// We don't modify or free() the "-" constant. The caller
|
|
|
|
// modifies this so don't make the struct itself const.
|
|
|
|
static char *names_stdin[2] = { (char *)"-", NULL };
|
|
|
|
args->arg_names = names_stdin;
|
|
|
|
args->arg_count = 1;
|
|
|
|
} else {
|
|
|
|
// We got at least one filename from the command line, or
|
|
|
|
// --files or --files0 was specified.
|
|
|
|
args->arg_names = argv + optind;
|
|
|
|
args->arg_count = argc - optind;
|
2007-12-08 23:42:33 +01:00
|
|
|
}
|
|
|
|
|
2008-11-19 19:46:52 +01:00
|
|
|
return;
|
2007-12-08 23:42:33 +01:00
|
|
|
}
|