1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief Argument parsing
6 /// \note Filter-specific options parsing is in options.c.
8 // Copyright (C) 2007 Lasse Collin
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
20 ///////////////////////////////////////////////////////////////////////////////
28 bool opt_stdout = false;
29 bool opt_force = false;
30 bool opt_keep_original = false;
32 // We don't modify or free() this, but we need to assign it in some
33 // non-const pointers.
34 const char *stdin_filename = "(stdin)";
38 parse_real(args_info *args, int argc, char **argv)
41 OPT_SUBBLOCK = INT_MIN,
56 static const char short_opts[] = "cC:dfF:hHlLkM:p:qrS:tT:vVz123456789";
58 static const struct option long_opts[] = {
60 { "compress", no_argument, NULL, 'z' },
61 { "decompress", no_argument, NULL, 'd' },
62 { "uncompress", no_argument, NULL, 'd' },
63 { "test", no_argument, NULL, 't' },
64 { "list", no_argument, NULL, 'l' },
65 { "info", no_argument, NULL, 'l' },
67 // Operation modifiers
68 { "keep", no_argument, NULL, 'k' },
69 { "force", no_argument, NULL, 'f' },
70 { "stdout", no_argument, NULL, 'c' },
71 { "to-stdout", no_argument, NULL, 'c' },
72 { "suffix", required_argument, NULL, 'S' },
73 // { "recursive", no_argument, NULL, 'r' }, // TODO
74 { "files", optional_argument, NULL, OPT_FILES },
75 { "files0", optional_argument, NULL, OPT_FILES0 },
77 // Basic compression settings
78 { "format", required_argument, NULL, 'F' },
79 { "check", required_argument, NULL, 'C' },
80 { "preset", required_argument, NULL, 'p' },
81 { "memory", required_argument, NULL, 'M' },
82 { "threads", required_argument, NULL, 'T' },
84 { "fast", no_argument, NULL, '1' },
85 { "best", no_argument, NULL, '9' },
88 { "lzma1", optional_argument, NULL, OPT_LZMA1 },
89 { "lzma2", optional_argument, NULL, OPT_LZMA2 },
90 { "x86", no_argument, NULL, OPT_X86 },
91 { "bcj", no_argument, NULL, OPT_X86 },
92 { "powerpc", no_argument, NULL, OPT_POWERPC },
93 { "ppc", no_argument, NULL, OPT_POWERPC },
94 { "ia64", no_argument, NULL, OPT_IA64 },
95 { "itanium", no_argument, NULL, OPT_IA64 },
96 { "arm", no_argument, NULL, OPT_ARM },
97 { "armthumb", no_argument, NULL, OPT_ARMTHUMB },
98 { "sparc", no_argument, NULL, OPT_SPARC },
99 { "delta", optional_argument, NULL, OPT_DELTA },
100 { "subblock", optional_argument, NULL, OPT_SUBBLOCK },
103 { "quiet", no_argument, NULL, 'q' },
104 { "verbose", no_argument, NULL, 'v' },
105 { "help", no_argument, NULL, 'h' },
106 { "long-help", no_argument, NULL, 'H' },
107 { "version", no_argument, NULL, 'V' },
114 while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL))
119 case '1': case '2': case '3': case '4':
120 case '5': case '6': case '7': case '8': case '9':
121 coder_set_preset(c - '0');
125 const uint64_t preset = str_to_uint64(
126 "preset", optarg, 1, 9);
127 coder_set_preset(preset);
133 // On 32-bit systems, SIZE_MAX would make more sense
134 // than UINT64_MAX. But use UINT64_MAX still so that
135 // scripts that assume > 4 GiB values don't break.
136 hardware_memlimit_set(str_to_uint64(
137 "memory", optarg, 0, UINT64_MAX));
146 opt_threads = str_to_uint64("threads", optarg,
152 // This doesn't return.
162 opt_mode = MODE_DECOMPRESS;
172 // This doesn't return.
177 // This doesn't return.
182 opt_mode = MODE_LIST;
187 opt_keep_original = true;
192 message_verbosity_decrease();
196 opt_mode = MODE_TEST;
201 message_verbosity_increase();
205 opt_mode = MODE_COMPRESS;
211 coder_add_filter(LZMA_FILTER_SUBBLOCK,
212 options_subblock(optarg));
216 coder_add_filter(LZMA_FILTER_X86, NULL);
220 coder_add_filter(LZMA_FILTER_POWERPC, NULL);
224 coder_add_filter(LZMA_FILTER_IA64, NULL);
228 coder_add_filter(LZMA_FILTER_ARM, NULL);
232 coder_add_filter(LZMA_FILTER_ARMTHUMB, NULL);
236 coder_add_filter(LZMA_FILTER_SPARC, NULL);
240 coder_add_filter(LZMA_FILTER_DELTA,
241 options_delta(optarg));
245 coder_add_filter(LZMA_FILTER_LZMA1,
246 options_lzma(optarg));
250 coder_add_filter(LZMA_FILTER_LZMA2,
251 options_lzma(optarg));
258 // Just in case, support both "lzma" and "alone" since
259 // the latter was used for forward compatibility in
260 // LZMA Utils 4.32.x.
261 static const struct {
263 enum format_type format;
265 { "auto", FORMAT_AUTO },
267 { "lzma", FORMAT_LZMA },
268 { "alone", FORMAT_LZMA },
269 // { "gzip", FORMAT_GZIP },
270 // { "gz", FORMAT_GZIP },
271 { "raw", FORMAT_RAW },
275 while (strcmp(types[i].str, optarg) != 0)
276 if (++i == ARRAY_SIZE(types))
277 message_fatal(_("%s: Unknown file "
281 opt_format = types[i].format;
287 static const struct {
291 { "none", LZMA_CHECK_NONE },
292 { "crc32", LZMA_CHECK_CRC32 },
293 { "crc64", LZMA_CHECK_CRC64 },
294 { "sha256", LZMA_CHECK_SHA256 },
298 while (strcmp(types[i].str, optarg) != 0) {
299 if (++i == ARRAY_SIZE(types))
300 message_fatal(_("%s: Unknown integrity"
301 "check type"), optarg);
304 coder_set_check(types[i].check);
309 args->files_delim = '\n';
314 if (args->files_name != NULL)
315 message_fatal(_("Only one file can be "
316 "specified with `--files'"
319 if (optarg == NULL) {
320 args->files_name = (char *)stdin_filename;
321 args->files_file = stdin;
323 args->files_name = optarg;
324 args->files_file = fopen(optarg,
325 c == OPT_FILES ? "r" : "rb");
326 if (args->files_file == NULL)
327 message_fatal("%s: %s", optarg,
344 parse_environment(args_info *args, char *argv0)
346 char *env = getenv("XZ_OPT");
350 // We modify the string, so make a copy of it.
353 // Calculate the number of arguments in env. argc stats at one
354 // to include space for the program name.
356 bool prev_was_space = true;
357 for (size_t i = 0; env[i] != '\0'; ++i) {
358 if (isspace(env[i])) {
359 prev_was_space = true;
360 } else if (prev_was_space) {
361 prev_was_space = false;
363 // Keep argc small enough to fit into a singed int
364 // and to keep it usable for memory allocation.
365 if (++argc == MIN(INT_MAX, SIZE_MAX / sizeof(char *)))
366 message_fatal(_("The environment variable "
367 "XZ_OPT contains too many "
372 // Allocate memory to hold pointers to the arguments. Add one to get
373 // space for the terminating NULL (if some systems happen to need it).
374 char **argv = xmalloc(((size_t)(argc) + 1) * sizeof(char *));
378 // Go through the string again. Split the arguments using '\0'
379 // characters and add pointers to the resulting strings to argv.
381 prev_was_space = true;
382 for (size_t i = 0; env[i] != '\0'; ++i) {
383 if (isspace(env[i])) {
384 prev_was_space = true;
386 } else if (prev_was_space) {
387 prev_was_space = false;
388 argv[argc++] = env + i;
392 // Parse the argument list we got from the environment. All non-option
393 // arguments i.e. filenames are ignored.
394 parse_real(args, argc, argv);
396 // Reset the state of the getopt_long() so that we can parse the
397 // command line options too. There are two incompatible ways to
408 // We don't need the argument list from environment anymore.
417 args_parse(args_info *args, int argc, char **argv)
419 // Initialize those parts of *args that we need later.
420 args->files_name = NULL;
421 args->files_file = NULL;
422 args->files_delim = '\0';
424 // Type of the file format to use when --format=auto or no --format
426 enum format_type format_compress_auto = FORMAT_XZ;
428 // Check how we were called.
430 // Remove the leading path name, if any.
431 const char *name = strrchr(argv[0], '/');
437 // NOTE: It's possible that name[0] is now '\0' if argv[0]
438 // is weird, but it doesn't matter here.
440 // The default file format is .lzma if the command name
442 if (strstr(name, "lz") != NULL)
443 format_compress_auto = FORMAT_LZMA;
446 if (strstr(name, "cat") != NULL) {
447 // Imply --decompress --stdout
448 opt_mode = MODE_DECOMPRESS;
450 } else if (strstr(name, "un") != NULL) {
451 // Imply --decompress
452 opt_mode = MODE_DECOMPRESS;
456 // First the flags from environment
457 parse_environment(args, argv[0]);
459 // Then from the command line
461 parse_real(args, argc, argv);
463 // Never remove the source file when the destination is not on disk.
464 // In test mode the data is written nowhere, but setting opt_stdout
465 // will make the rest of the code behave well.
466 if (opt_stdout || opt_mode == MODE_TEST) {
467 opt_keep_original = true;
471 // If no --format flag was used, or it was --format=auto, we need to
472 // decide what is the target file format we are going to use. This
473 // depends on how we were called (checked earlier in this function).
474 if (opt_mode == MODE_COMPRESS && opt_format == FORMAT_AUTO)
475 opt_format = format_compress_auto;
477 // Compression settings need to be validated (options themselves and
478 // their memory usage) when compressing to any file format. It has to
479 // be done also when uncompressing raw data, since for raw decoding
480 // the options given on the command line are used to know what kind
481 // of raw data we are supposed to decode.
482 if (opt_mode == MODE_COMPRESS || opt_format == FORMAT_RAW)
483 coder_set_compression_settings();
485 // If no filenames are given, use stdin.
486 if (argv[optind] == NULL && args->files_name == NULL) {
487 // We don't modify or free() the "-" constant. The caller
488 // modifies this so don't make the struct itself const.
489 static char *names_stdin[2] = { (char *)"-", NULL };
490 args->arg_names = names_stdin;
493 // We got at least one filename from the command line, or
494 // --files or --files0 was specified.
495 args->arg_names = argv + optind;
496 args->arg_count = argc - optind;