xref: /freebsd/contrib/xz/src/xz/args.c (revision 06c3fb27)
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       args.c
4 /// \brief      Argument parsing
5 ///
6 /// \note       Filter-specific options parsing is in options.c.
7 //
8 //  Author:     Lasse Collin
9 //
10 //  This file has been put into the public domain.
11 //  You can do whatever you want with this file.
12 //
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 #include "private.h"
16 
17 #include "getopt.h"
18 #include <ctype.h>
19 
20 
21 bool opt_stdout = false;
22 bool opt_force = false;
23 bool opt_keep_original = false;
24 bool opt_robot = false;
25 bool opt_ignore_check = false;
26 
27 // We don't modify or free() this, but we need to assign it in some
28 // non-const pointers.
29 const char stdin_filename[] = "(stdin)";
30 
31 
32 /// Parse and set the memory usage limit for compression, decompression,
33 /// and/or multithreaded decompression.
34 static void
35 parse_memlimit(const char *name, const char *name_percentage, const char *str,
36 		bool set_compress, bool set_decompress, bool set_mtdec)
37 {
38 	bool is_percentage = false;
39 	uint64_t value;
40 
41 	const size_t len = strlen(str);
42 	if (len > 0 && str[len - 1] == '%') {
43 		// Make a copy so that we can get rid of %.
44 		//
45 		// In the past str wasn't const and we modified it directly
46 		// but that modified argv[] and thus affected what was visible
47 		// in "ps auxf" or similar tools which was confusing. For
48 		// example, --memlimit=50% would show up as --memlimit=50
49 		// since the percent sign was overwritten here.
50 		char *s = xstrdup(str);
51 		s[len - 1] = '\0';
52 		is_percentage = true;
53 		value = str_to_uint64(name_percentage, s, 1, 100);
54 		free(s);
55 	} else {
56 		// On 32-bit systems, SIZE_MAX would make more sense than
57 		// UINT64_MAX. But use UINT64_MAX still so that scripts
58 		// that assume > 4 GiB values don't break.
59 		value = str_to_uint64(name, str, 0, UINT64_MAX);
60 	}
61 
62 	hardware_memlimit_set(value, set_compress, set_decompress, set_mtdec,
63 			is_percentage);
64 	return;
65 }
66 
67 
68 static void
69 parse_block_list(const char *str_const)
70 {
71 	// We need a modifiable string in the for-loop.
72 	char *str_start = xstrdup(str_const);
73 	char *str = str_start;
74 
75 	// It must be non-empty and not begin with a comma.
76 	if (str[0] == '\0' || str[0] == ',')
77 		message_fatal(_("%s: Invalid argument to --block-list"), str);
78 
79 	// Count the number of comma-separated strings.
80 	size_t count = 1;
81 	for (size_t i = 0; str[i] != '\0'; ++i)
82 		if (str[i] == ',')
83 			++count;
84 
85 	// Prevent an unlikely integer overflow.
86 	if (count > SIZE_MAX / sizeof(uint64_t) - 1)
87 		message_fatal(_("%s: Too many arguments to --block-list"),
88 				str);
89 
90 	// Allocate memory to hold all the sizes specified.
91 	// If --block-list was specified already, its value is forgotten.
92 	free(opt_block_list);
93 	opt_block_list = xmalloc((count + 1) * sizeof(uint64_t));
94 
95 	for (size_t i = 0; i < count; ++i) {
96 		// Locate the next comma and replace it with \0.
97 		char *p = strchr(str, ',');
98 		if (p != NULL)
99 			*p = '\0';
100 
101 		if (str[0] == '\0') {
102 			// There is no string, that is, a comma follows
103 			// another comma. Use the previous value.
104 			//
105 			// NOTE: We checked earlier that the first char
106 			// of the whole list cannot be a comma.
107 			assert(i > 0);
108 			opt_block_list[i] = opt_block_list[i - 1];
109 		} else {
110 			opt_block_list[i] = str_to_uint64("block-list", str,
111 					0, UINT64_MAX);
112 
113 			// Zero indicates no more new Blocks.
114 			if (opt_block_list[i] == 0) {
115 				if (i + 1 != count)
116 					message_fatal(_("0 can only be used "
117 							"as the last element "
118 							"in --block-list"));
119 
120 				opt_block_list[i] = UINT64_MAX;
121 			}
122 		}
123 
124 		str = p + 1;
125 	}
126 
127 	// Terminate the array.
128 	opt_block_list[count] = 0;
129 
130 	free(str_start);
131 	return;
132 }
133 
134 
135 static void
136 parse_real(args_info *args, int argc, char **argv)
137 {
138 	enum {
139 		OPT_X86 = INT_MIN,
140 		OPT_POWERPC,
141 		OPT_IA64,
142 		OPT_ARM,
143 		OPT_ARMTHUMB,
144 		OPT_ARM64,
145 		OPT_SPARC,
146 		OPT_DELTA,
147 		OPT_LZMA1,
148 		OPT_LZMA2,
149 
150 		OPT_SINGLE_STREAM,
151 		OPT_NO_SPARSE,
152 		OPT_FILES,
153 		OPT_FILES0,
154 		OPT_BLOCK_SIZE,
155 		OPT_BLOCK_LIST,
156 		OPT_MEM_COMPRESS,
157 		OPT_MEM_DECOMPRESS,
158 		OPT_MEM_MT_DECOMPRESS,
159 		OPT_NO_ADJUST,
160 		OPT_INFO_MEMORY,
161 		OPT_ROBOT,
162 		OPT_FLUSH_TIMEOUT,
163 		OPT_IGNORE_CHECK,
164 	};
165 
166 	static const char short_opts[]
167 			= "cC:defF:hHlkM:qQrS:tT:vVz0123456789";
168 
169 	static const struct option long_opts[] = {
170 		// Operation mode
171 		{ "compress",     no_argument,       NULL,  'z' },
172 		{ "decompress",   no_argument,       NULL,  'd' },
173 		{ "uncompress",   no_argument,       NULL,  'd' },
174 		{ "test",         no_argument,       NULL,  't' },
175 		{ "list",         no_argument,       NULL,  'l' },
176 
177 		// Operation modifiers
178 		{ "keep",         no_argument,       NULL,  'k' },
179 		{ "force",        no_argument,       NULL,  'f' },
180 		{ "stdout",       no_argument,       NULL,  'c' },
181 		{ "to-stdout",    no_argument,       NULL,  'c' },
182 		{ "single-stream", no_argument,      NULL,  OPT_SINGLE_STREAM },
183 		{ "no-sparse",    no_argument,       NULL,  OPT_NO_SPARSE },
184 		{ "suffix",       required_argument, NULL,  'S' },
185 		// { "recursive",      no_argument,       NULL,  'r' }, // TODO
186 		{ "files",        optional_argument, NULL,  OPT_FILES },
187 		{ "files0",       optional_argument, NULL,  OPT_FILES0 },
188 
189 		// Basic compression settings
190 		{ "format",       required_argument, NULL,  'F' },
191 		{ "check",        required_argument, NULL,  'C' },
192 		{ "ignore-check", no_argument,       NULL,  OPT_IGNORE_CHECK },
193 		{ "block-size",   required_argument, NULL,  OPT_BLOCK_SIZE },
194 		{ "block-list",  required_argument, NULL,  OPT_BLOCK_LIST },
195 		{ "memlimit-compress",   required_argument, NULL, OPT_MEM_COMPRESS },
196 		{ "memlimit-decompress", required_argument, NULL, OPT_MEM_DECOMPRESS },
197 		{ "memlimit-mt-decompress", required_argument, NULL, OPT_MEM_MT_DECOMPRESS },
198 		{ "memlimit",     required_argument, NULL,  'M' },
199 		{ "memory",       required_argument, NULL,  'M' }, // Old alias
200 		{ "no-adjust",    no_argument,       NULL,  OPT_NO_ADJUST },
201 		{ "threads",      required_argument, NULL,  'T' },
202 		{ "flush-timeout", required_argument, NULL, OPT_FLUSH_TIMEOUT },
203 
204 		{ "extreme",      no_argument,       NULL,  'e' },
205 		{ "fast",         no_argument,       NULL,  '0' },
206 		{ "best",         no_argument,       NULL,  '9' },
207 
208 		// Filters
209 		{ "lzma1",        optional_argument, NULL,  OPT_LZMA1 },
210 		{ "lzma2",        optional_argument, NULL,  OPT_LZMA2 },
211 		{ "x86",          optional_argument, NULL,  OPT_X86 },
212 		{ "powerpc",      optional_argument, NULL,  OPT_POWERPC },
213 		{ "ia64",         optional_argument, NULL,  OPT_IA64 },
214 		{ "arm",          optional_argument, NULL,  OPT_ARM },
215 		{ "armthumb",     optional_argument, NULL,  OPT_ARMTHUMB },
216 		{ "arm64",        optional_argument, NULL,  OPT_ARM64 },
217 		{ "sparc",        optional_argument, NULL,  OPT_SPARC },
218 		{ "delta",        optional_argument, NULL,  OPT_DELTA },
219 
220 		// Other options
221 		{ "quiet",        no_argument,       NULL,  'q' },
222 		{ "verbose",      no_argument,       NULL,  'v' },
223 		{ "no-warn",      no_argument,       NULL,  'Q' },
224 		{ "robot",        no_argument,       NULL,  OPT_ROBOT },
225 		{ "info-memory",  no_argument,       NULL,  OPT_INFO_MEMORY },
226 		{ "help",         no_argument,       NULL,  'h' },
227 		{ "long-help",    no_argument,       NULL,  'H' },
228 		{ "version",      no_argument,       NULL,  'V' },
229 
230 		{ NULL,           0,                 NULL,   0 }
231 	};
232 
233 	int c;
234 
235 	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL))
236 			!= -1) {
237 		switch (c) {
238 		// Compression preset (also for decompression if --format=raw)
239 		case '0': case '1': case '2': case '3': case '4':
240 		case '5': case '6': case '7': case '8': case '9':
241 			coder_set_preset((uint32_t)(c - '0'));
242 			break;
243 
244 		// --memlimit-compress
245 		case OPT_MEM_COMPRESS:
246 			parse_memlimit("memlimit-compress",
247 					"memlimit-compress%", optarg,
248 					true, false, false);
249 			break;
250 
251 		// --memlimit-decompress
252 		case OPT_MEM_DECOMPRESS:
253 			parse_memlimit("memlimit-decompress",
254 					"memlimit-decompress%", optarg,
255 					false, true, false);
256 			break;
257 
258 		// --memlimit-mt-decompress
259 		case OPT_MEM_MT_DECOMPRESS:
260 			parse_memlimit("memlimit-mt-decompress",
261 					"memlimit-mt-decompress%", optarg,
262 					false, false, true);
263 			break;
264 
265 		// --memlimit
266 		case 'M':
267 			parse_memlimit("memlimit", "memlimit%", optarg,
268 					true, true, true);
269 			break;
270 
271 		// --suffix
272 		case 'S':
273 			suffix_set(optarg);
274 			break;
275 
276 		case 'T': {
277 			// Since xz 5.4.0: Ignore leading '+' first.
278 			const char *s = optarg;
279 			if (optarg[0] == '+')
280 				++s;
281 
282 			// The max is from src/liblzma/common/common.h.
283 			uint32_t t = str_to_uint64("threads", s, 0, 16384);
284 
285 			// If leading '+' was used then use multi-threaded
286 			// mode even if exactly one thread was specified.
287 			if (t == 1 && optarg[0] == '+')
288 				t = UINT32_MAX;
289 
290 			hardware_threads_set(t);
291 			break;
292 		}
293 
294 		// --version
295 		case 'V':
296 			// This doesn't return.
297 			message_version();
298 
299 		// --stdout
300 		case 'c':
301 			opt_stdout = true;
302 			break;
303 
304 		// --decompress
305 		case 'd':
306 			opt_mode = MODE_DECOMPRESS;
307 			break;
308 
309 		// --extreme
310 		case 'e':
311 			coder_set_extreme();
312 			break;
313 
314 		// --force
315 		case 'f':
316 			opt_force = true;
317 			break;
318 
319 		// --info-memory
320 		case OPT_INFO_MEMORY:
321 			// This doesn't return.
322 			hardware_memlimit_show();
323 
324 		// --help
325 		case 'h':
326 			// This doesn't return.
327 			message_help(false);
328 
329 		// --long-help
330 		case 'H':
331 			// This doesn't return.
332 			message_help(true);
333 
334 		// --list
335 		case 'l':
336 			opt_mode = MODE_LIST;
337 			break;
338 
339 		// --keep
340 		case 'k':
341 			opt_keep_original = true;
342 			break;
343 
344 		// --quiet
345 		case 'q':
346 			message_verbosity_decrease();
347 			break;
348 
349 		case 'Q':
350 			set_exit_no_warn();
351 			break;
352 
353 		case 't':
354 			opt_mode = MODE_TEST;
355 			break;
356 
357 		// --verbose
358 		case 'v':
359 			message_verbosity_increase();
360 			break;
361 
362 		// --robot
363 		case OPT_ROBOT:
364 			opt_robot = true;
365 
366 			// This is to make sure that floating point numbers
367 			// always have a dot as decimal separator.
368 			setlocale(LC_NUMERIC, "C");
369 			break;
370 
371 		case 'z':
372 			opt_mode = MODE_COMPRESS;
373 			break;
374 
375 		// Filter setup
376 
377 		case OPT_X86:
378 			coder_add_filter(LZMA_FILTER_X86,
379 					options_bcj(optarg));
380 			break;
381 
382 		case OPT_POWERPC:
383 			coder_add_filter(LZMA_FILTER_POWERPC,
384 					options_bcj(optarg));
385 			break;
386 
387 		case OPT_IA64:
388 			coder_add_filter(LZMA_FILTER_IA64,
389 					options_bcj(optarg));
390 			break;
391 
392 		case OPT_ARM:
393 			coder_add_filter(LZMA_FILTER_ARM,
394 					options_bcj(optarg));
395 			break;
396 
397 		case OPT_ARMTHUMB:
398 			coder_add_filter(LZMA_FILTER_ARMTHUMB,
399 					options_bcj(optarg));
400 			break;
401 
402 		case OPT_ARM64:
403 			coder_add_filter(LZMA_FILTER_ARM64,
404 					options_bcj(optarg));
405 			break;
406 
407 		case OPT_SPARC:
408 			coder_add_filter(LZMA_FILTER_SPARC,
409 					options_bcj(optarg));
410 			break;
411 
412 		case OPT_DELTA:
413 			coder_add_filter(LZMA_FILTER_DELTA,
414 					options_delta(optarg));
415 			break;
416 
417 		case OPT_LZMA1:
418 			coder_add_filter(LZMA_FILTER_LZMA1,
419 					options_lzma(optarg));
420 			break;
421 
422 		case OPT_LZMA2:
423 			coder_add_filter(LZMA_FILTER_LZMA2,
424 					options_lzma(optarg));
425 			break;
426 
427 		// Other
428 
429 		// --format
430 		case 'F': {
431 			// Just in case, support both "lzma" and "alone" since
432 			// the latter was used for forward compatibility in
433 			// LZMA Utils 4.32.x.
434 			static const struct {
435 				char str[8];
436 				enum format_type format;
437 			} types[] = {
438 				{ "auto",   FORMAT_AUTO },
439 				{ "xz",     FORMAT_XZ },
440 				{ "lzma",   FORMAT_LZMA },
441 				{ "alone",  FORMAT_LZMA },
442 #ifdef HAVE_LZIP_DECODER
443 				{ "lzip",   FORMAT_LZIP },
444 #endif
445 				{ "raw",    FORMAT_RAW },
446 			};
447 
448 			size_t i = 0;
449 			while (strcmp(types[i].str, optarg) != 0)
450 				if (++i == ARRAY_SIZE(types))
451 					message_fatal(_("%s: Unknown file "
452 							"format type"),
453 							optarg);
454 
455 			opt_format = types[i].format;
456 			break;
457 		}
458 
459 		// --check
460 		case 'C': {
461 			static const struct {
462 				char str[8];
463 				lzma_check check;
464 			} types[] = {
465 				{ "none",   LZMA_CHECK_NONE },
466 				{ "crc32",  LZMA_CHECK_CRC32 },
467 				{ "crc64",  LZMA_CHECK_CRC64 },
468 				{ "sha256", LZMA_CHECK_SHA256 },
469 			};
470 
471 			size_t i = 0;
472 			while (strcmp(types[i].str, optarg) != 0) {
473 				if (++i == ARRAY_SIZE(types))
474 					message_fatal(_("%s: Unsupported "
475 							"integrity "
476 							"check type"), optarg);
477 			}
478 
479 			// Use a separate check in case we are using different
480 			// liblzma than what was used to compile us.
481 			if (!lzma_check_is_supported(types[i].check))
482 				message_fatal(_("%s: Unsupported integrity "
483 						"check type"), optarg);
484 
485 			coder_set_check(types[i].check);
486 			break;
487 		}
488 
489 		case OPT_IGNORE_CHECK:
490 			opt_ignore_check = true;
491 			break;
492 
493 		case OPT_BLOCK_SIZE:
494 			opt_block_size = str_to_uint64("block-size", optarg,
495 					0, LZMA_VLI_MAX);
496 			break;
497 
498 		case OPT_BLOCK_LIST: {
499 			parse_block_list(optarg);
500 			break;
501 		}
502 
503 		case OPT_SINGLE_STREAM:
504 			opt_single_stream = true;
505 			break;
506 
507 		case OPT_NO_SPARSE:
508 			io_no_sparse();
509 			break;
510 
511 		case OPT_FILES:
512 			args->files_delim = '\n';
513 
514 		// Fall through
515 
516 		case OPT_FILES0:
517 			if (args->files_name != NULL)
518 				message_fatal(_("Only one file can be "
519 						"specified with `--files' "
520 						"or `--files0'."));
521 
522 			if (optarg == NULL) {
523 				args->files_name = stdin_filename;
524 				args->files_file = stdin;
525 			} else {
526 				args->files_name = optarg;
527 				args->files_file = fopen(optarg,
528 						c == OPT_FILES ? "r" : "rb");
529 				if (args->files_file == NULL)
530 					// TRANSLATORS: This is a translatable
531 					// string because French needs a space
532 					// before the colon ("%s : %s").
533 					message_fatal(_("%s: %s"), optarg,
534 							strerror(errno));
535 			}
536 
537 			break;
538 
539 		case OPT_NO_ADJUST:
540 			opt_auto_adjust = false;
541 			break;
542 
543 		case OPT_FLUSH_TIMEOUT:
544 			opt_flush_timeout = str_to_uint64("flush-timeout",
545 					optarg, 0, UINT64_MAX);
546 			break;
547 
548 		default:
549 			message_try_help();
550 			tuklib_exit(E_ERROR, E_ERROR, false);
551 		}
552 	}
553 
554 	return;
555 }
556 
557 
558 static void
559 parse_environment(args_info *args, char *argv0, const char *varname)
560 {
561 	char *env = getenv(varname);
562 	if (env == NULL)
563 		return;
564 
565 	// We modify the string, so make a copy of it.
566 	env = xstrdup(env);
567 
568 	// Calculate the number of arguments in env. argc stats at one
569 	// to include space for the program name.
570 	int argc = 1;
571 	bool prev_was_space = true;
572 	for (size_t i = 0; env[i] != '\0'; ++i) {
573 		// NOTE: Cast to unsigned char is needed so that correct
574 		// value gets passed to isspace(), which expects
575 		// unsigned char cast to int. Casting to int is done
576 		// automatically due to integer promotion, but we need to
577 		// force char to unsigned char manually. Otherwise 8-bit
578 		// characters would get promoted to wrong value if
579 		// char is signed.
580 		if (isspace((unsigned char)env[i])) {
581 			prev_was_space = true;
582 		} else if (prev_was_space) {
583 			prev_was_space = false;
584 
585 			// Keep argc small enough to fit into a signed int
586 			// and to keep it usable for memory allocation.
587 			if (++argc == my_min(
588 					INT_MAX, SIZE_MAX / sizeof(char *)))
589 				message_fatal(_("The environment variable "
590 						"%s contains too many "
591 						"arguments"), varname);
592 		}
593 	}
594 
595 	// Allocate memory to hold pointers to the arguments. Add one to get
596 	// space for the terminating NULL (if some systems happen to need it).
597 	char **argv = xmalloc(((size_t)(argc) + 1) * sizeof(char *));
598 	argv[0] = argv0;
599 	argv[argc] = NULL;
600 
601 	// Go through the string again. Split the arguments using '\0'
602 	// characters and add pointers to the resulting strings to argv.
603 	argc = 1;
604 	prev_was_space = true;
605 	for (size_t i = 0; env[i] != '\0'; ++i) {
606 		if (isspace((unsigned char)env[i])) {
607 			prev_was_space = true;
608 			env[i] = '\0';
609 		} else if (prev_was_space) {
610 			prev_was_space = false;
611 			argv[argc++] = env + i;
612 		}
613 	}
614 
615 	// Parse the argument list we got from the environment. All non-option
616 	// arguments i.e. filenames are ignored.
617 	parse_real(args, argc, argv);
618 
619 	// Reset the state of the getopt_long() so that we can parse the
620 	// command line options too. There are two incompatible ways to
621 	// do it.
622 #ifdef HAVE_OPTRESET
623 	// BSD
624 	optind = 1;
625 	optreset = 1;
626 #else
627 	// GNU, Solaris
628 	optind = 0;
629 #endif
630 
631 	// We don't need the argument list from environment anymore.
632 	free(argv);
633 	free(env);
634 
635 	return;
636 }
637 
638 
639 extern void
640 args_parse(args_info *args, int argc, char **argv)
641 {
642 	// Initialize those parts of *args that we need later.
643 	args->files_name = NULL;
644 	args->files_file = NULL;
645 	args->files_delim = '\0';
646 
647 	// Check how we were called.
648 	{
649 		// Remove the leading path name, if any.
650 		const char *name = strrchr(argv[0], '/');
651 		if (name == NULL)
652 			name = argv[0];
653 		else
654 			++name;
655 
656 		// NOTE: It's possible that name[0] is now '\0' if argv[0]
657 		// is weird, but it doesn't matter here.
658 
659 		// Look for full command names instead of substrings like
660 		// "un", "cat", and "lz" to reduce possibility of false
661 		// positives when the programs have been renamed.
662 		if (strstr(name, "xzcat") != NULL) {
663 			opt_mode = MODE_DECOMPRESS;
664 			opt_stdout = true;
665 		} else if (strstr(name, "unxz") != NULL) {
666 			opt_mode = MODE_DECOMPRESS;
667 		} else if (strstr(name, "lzcat") != NULL) {
668 			opt_format = FORMAT_LZMA;
669 			opt_mode = MODE_DECOMPRESS;
670 			opt_stdout = true;
671 		} else if (strstr(name, "unlzma") != NULL) {
672 			opt_format = FORMAT_LZMA;
673 			opt_mode = MODE_DECOMPRESS;
674 		} else if (strstr(name, "lzma") != NULL) {
675 			opt_format = FORMAT_LZMA;
676 		}
677 	}
678 
679 	// First the flags from the environment
680 	parse_environment(args, argv[0], "XZ_DEFAULTS");
681 	parse_environment(args, argv[0], "XZ_OPT");
682 
683 	// Then from the command line
684 	parse_real(args, argc, argv);
685 
686 	// If encoder or decoder support was omitted at build time,
687 	// show an error now so that the rest of the code can rely on
688 	// that whatever is in opt_mode is also supported.
689 #ifndef HAVE_ENCODERS
690 	if (opt_mode == MODE_COMPRESS)
691 		message_fatal(_("Compression support was disabled "
692 				"at build time"));
693 #endif
694 #ifndef HAVE_DECODERS
695 	// Even MODE_LIST cannot work without decoder support so MODE_COMPRESS
696 	// is the only valid choice.
697 	if (opt_mode != MODE_COMPRESS)
698 		message_fatal(_("Decompression support was disabled "
699 				"at build time"));
700 #endif
701 
702 #ifdef HAVE_LZIP_DECODER
703 	if (opt_mode == MODE_COMPRESS && opt_format == FORMAT_LZIP)
704 		message_fatal(_("Compression of lzip files (.lz) "
705 				"is not supported"));
706 #endif
707 
708 	// Never remove the source file when the destination is not on disk.
709 	// In test mode the data is written nowhere, but setting opt_stdout
710 	// will make the rest of the code behave well.
711 	if (opt_stdout || opt_mode == MODE_TEST) {
712 		opt_keep_original = true;
713 		opt_stdout = true;
714 	}
715 
716 	// When compressing, if no --format flag was used, or it
717 	// was --format=auto, we compress to the .xz format.
718 	if (opt_mode == MODE_COMPRESS && opt_format == FORMAT_AUTO)
719 		opt_format = FORMAT_XZ;
720 
721 	// Compression settings need to be validated (options themselves and
722 	// their memory usage) when compressing to any file format. It has to
723 	// be done also when uncompressing raw data, since for raw decoding
724 	// the options given on the command line are used to know what kind
725 	// of raw data we are supposed to decode.
726 	if (opt_mode == MODE_COMPRESS || (opt_format == FORMAT_RAW
727 			&& opt_mode != MODE_LIST))
728 		coder_set_compression_settings();
729 
730 	// If raw format is used and a custom suffix is not provided,
731 	// then only stdout mode can be used when compressing or decompressing.
732 	if (opt_format == FORMAT_RAW && !suffix_is_set() && !opt_stdout
733 			&& (opt_mode == MODE_COMPRESS
734 				|| opt_mode == MODE_DECOMPRESS))
735 		message_fatal(_("With --format=raw, --suffix=.SUF is "
736 				"required unless writing to stdout"));
737 
738 	// If no filenames are given, use stdin.
739 	if (argv[optind] == NULL && args->files_name == NULL) {
740 		// We don't modify or free() the "-" constant. The caller
741 		// modifies this so don't make the struct itself const.
742 		static char *names_stdin[2] = { (char *)"-", NULL };
743 		args->arg_names = names_stdin;
744 		args->arg_count = 1;
745 	} else {
746 		// We got at least one filename from the command line, or
747 		// --files or --files0 was specified.
748 		args->arg_names = argv + optind;
749 		args->arg_count = (unsigned int)(argc - optind);
750 	}
751 
752 	return;
753 }
754 
755 
756 #ifndef NDEBUG
757 extern void
758 args_free(void)
759 {
760 	free(opt_block_list);
761 	return;
762 }
763 #endif
764