xref: /dflybsd-src/contrib/xz/src/lzmainfo/lzmainfo.c (revision f9ac416ffa1e59cc77781072f0678b63379201cf)
12940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
22940b44dSPeter Avalos //
32940b44dSPeter Avalos /// \file       lzmainfo.c
42940b44dSPeter Avalos /// \brief      lzmainfo tool for compatibility with LZMA Utils
52940b44dSPeter Avalos //
62940b44dSPeter Avalos //  Author:     Lasse Collin
72940b44dSPeter Avalos //
82940b44dSPeter Avalos //  This file has been put into the public domain.
92940b44dSPeter Avalos //  You can do whatever you want with this file.
102940b44dSPeter Avalos //
112940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
122940b44dSPeter Avalos 
132940b44dSPeter Avalos #include "sysdefs.h"
142940b44dSPeter Avalos #include <stdio.h>
152940b44dSPeter Avalos #include <errno.h>
162940b44dSPeter Avalos 
172940b44dSPeter Avalos #include "lzma.h"
182940b44dSPeter Avalos #include "getopt.h"
192940b44dSPeter Avalos #include "tuklib_gettext.h"
202940b44dSPeter Avalos #include "tuklib_progname.h"
212940b44dSPeter Avalos #include "tuklib_exit.h"
222940b44dSPeter Avalos 
232940b44dSPeter Avalos #ifdef TUKLIB_DOSLIKE
242940b44dSPeter Avalos #	include <fcntl.h>
252940b44dSPeter Avalos #	include <io.h>
262940b44dSPeter Avalos #endif
272940b44dSPeter Avalos 
282940b44dSPeter Avalos 
29*114db65bSPeter Avalos static void lzma_attribute((__noreturn__))
help(void)302940b44dSPeter Avalos help(void)
312940b44dSPeter Avalos {
322940b44dSPeter Avalos 	printf(
332940b44dSPeter Avalos _("Usage: %s [--help] [--version] [FILE]...\n"
342940b44dSPeter Avalos "Show information stored in the .lzma file header"), progname);
352940b44dSPeter Avalos 
362940b44dSPeter Avalos 	printf(_(
372940b44dSPeter Avalos "\nWith no FILE, or when FILE is -, read standard input.\n"));
382940b44dSPeter Avalos 	printf("\n");
392940b44dSPeter Avalos 
402940b44dSPeter Avalos 	printf(_("Report bugs to <%s> (in English or Finnish).\n"),
412940b44dSPeter Avalos 			PACKAGE_BUGREPORT);
422940b44dSPeter Avalos 	printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
432940b44dSPeter Avalos 
442940b44dSPeter Avalos 	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
452940b44dSPeter Avalos }
462940b44dSPeter Avalos 
472940b44dSPeter Avalos 
48*114db65bSPeter Avalos static void lzma_attribute((__noreturn__))
version(void)492940b44dSPeter Avalos version(void)
502940b44dSPeter Avalos {
512940b44dSPeter Avalos 	puts("lzmainfo (" PACKAGE_NAME ") " LZMA_VERSION_STRING);
522940b44dSPeter Avalos 	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
532940b44dSPeter Avalos }
542940b44dSPeter Avalos 
552940b44dSPeter Avalos 
562940b44dSPeter Avalos /// Parse command line options.
572940b44dSPeter Avalos static void
parse_args(int argc,char ** argv)582940b44dSPeter Avalos parse_args(int argc, char **argv)
592940b44dSPeter Avalos {
602940b44dSPeter Avalos 	enum {
612940b44dSPeter Avalos 		OPT_HELP,
622940b44dSPeter Avalos 		OPT_VERSION,
632940b44dSPeter Avalos 	};
642940b44dSPeter Avalos 
652940b44dSPeter Avalos 	static const struct option long_opts[] = {
662940b44dSPeter Avalos 		{ "help",    no_argument, NULL, OPT_HELP },
672940b44dSPeter Avalos 		{ "version", no_argument, NULL, OPT_VERSION },
682940b44dSPeter Avalos 		{ NULL,      0,           NULL, 0 }
692940b44dSPeter Avalos 	};
702940b44dSPeter Avalos 
712940b44dSPeter Avalos 	int c;
722940b44dSPeter Avalos 	while ((c = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
732940b44dSPeter Avalos 		switch (c) {
742940b44dSPeter Avalos 		case OPT_HELP:
752940b44dSPeter Avalos 			help();
762940b44dSPeter Avalos 
772940b44dSPeter Avalos 		case OPT_VERSION:
782940b44dSPeter Avalos 			version();
792940b44dSPeter Avalos 
802940b44dSPeter Avalos 		default:
812940b44dSPeter Avalos 			exit(EXIT_FAILURE);
822940b44dSPeter Avalos 		}
832940b44dSPeter Avalos 	}
842940b44dSPeter Avalos 
852940b44dSPeter Avalos 	return;
862940b44dSPeter Avalos }
872940b44dSPeter Avalos 
882940b44dSPeter Avalos 
892940b44dSPeter Avalos /// Primitive base-2 logarithm for integers
902940b44dSPeter Avalos static uint32_t
my_log2(uint32_t n)912940b44dSPeter Avalos my_log2(uint32_t n)
922940b44dSPeter Avalos {
932940b44dSPeter Avalos 	uint32_t e;
942940b44dSPeter Avalos 	for (e = 0; n > 1; ++e, n /= 2) ;
952940b44dSPeter Avalos 	return e;
962940b44dSPeter Avalos }
972940b44dSPeter Avalos 
982940b44dSPeter Avalos 
992940b44dSPeter Avalos /// Parse the .lzma header and display information about it.
1002940b44dSPeter Avalos static bool
lzmainfo(const char * name,FILE * f)1012940b44dSPeter Avalos lzmainfo(const char *name, FILE *f)
1022940b44dSPeter Avalos {
1032940b44dSPeter Avalos 	uint8_t buf[13];
1042940b44dSPeter Avalos 	const size_t size = fread(buf, 1, sizeof(buf), f);
1052940b44dSPeter Avalos 	if (size != 13) {
1062940b44dSPeter Avalos 		fprintf(stderr, "%s: %s: %s\n", progname, name,
1072940b44dSPeter Avalos 				ferror(f) ? strerror(errno)
1082940b44dSPeter Avalos 				: _("File is too small to be a .lzma file"));
1092940b44dSPeter Avalos 		return true;
1102940b44dSPeter Avalos 	}
1112940b44dSPeter Avalos 
1122940b44dSPeter Avalos 	lzma_filter filter = { .id = LZMA_FILTER_LZMA1 };
1132940b44dSPeter Avalos 
1142940b44dSPeter Avalos 	// Parse the first five bytes.
1152940b44dSPeter Avalos 	switch (lzma_properties_decode(&filter, NULL, buf, 5)) {
1162940b44dSPeter Avalos 	case LZMA_OK:
1172940b44dSPeter Avalos 		break;
1182940b44dSPeter Avalos 
1192940b44dSPeter Avalos 	case LZMA_OPTIONS_ERROR:
1202940b44dSPeter Avalos 		fprintf(stderr, "%s: %s: %s\n", progname, name,
1212940b44dSPeter Avalos 				_("Not a .lzma file"));
1222940b44dSPeter Avalos 		return true;
1232940b44dSPeter Avalos 
1242940b44dSPeter Avalos 	case LZMA_MEM_ERROR:
1252940b44dSPeter Avalos 		fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
1262940b44dSPeter Avalos 		exit(EXIT_FAILURE);
1272940b44dSPeter Avalos 
1282940b44dSPeter Avalos 	default:
1292940b44dSPeter Avalos 		fprintf(stderr, "%s: %s\n", progname,
1302940b44dSPeter Avalos 				_("Internal error (bug)"));
1312940b44dSPeter Avalos 		exit(EXIT_FAILURE);
1322940b44dSPeter Avalos 	}
1332940b44dSPeter Avalos 
1342940b44dSPeter Avalos 	// Uncompressed size
1352940b44dSPeter Avalos 	uint64_t uncompressed_size = 0;
1362940b44dSPeter Avalos 	for (size_t i = 0; i < 8; ++i)
1372940b44dSPeter Avalos 		uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8);
1382940b44dSPeter Avalos 
1392940b44dSPeter Avalos 	// Display the results. We don't want to translate these and also
1402940b44dSPeter Avalos 	// will use MB instead of MiB, because someone could be parsing
1412940b44dSPeter Avalos 	// this output and we don't want to break that when people move
1422940b44dSPeter Avalos 	// from LZMA Utils to XZ Utils.
1432940b44dSPeter Avalos 	if (f != stdin)
1442940b44dSPeter Avalos 		printf("%s\n", name);
1452940b44dSPeter Avalos 
1462940b44dSPeter Avalos 	printf("Uncompressed size:             ");
1472940b44dSPeter Avalos 	if (uncompressed_size == UINT64_MAX)
1482940b44dSPeter Avalos 		printf("Unknown");
1492940b44dSPeter Avalos 	else
1502940b44dSPeter Avalos 		printf("%" PRIu64 " MB (%" PRIu64 " bytes)",
1512940b44dSPeter Avalos 				(uncompressed_size + 512 * 1024)
1522940b44dSPeter Avalos 					/ (1024 * 1024),
1532940b44dSPeter Avalos 				uncompressed_size);
1542940b44dSPeter Avalos 
1552940b44dSPeter Avalos 	lzma_options_lzma *opt = filter.options;
1562940b44dSPeter Avalos 
1572940b44dSPeter Avalos 	printf("\nDictionary size:               "
1582940b44dSPeter Avalos 			"%" PRIu32 " MB (2^%" PRIu32 " bytes)\n"
1592940b44dSPeter Avalos 			"Literal context bits (lc):     %" PRIu32 "\n"
1602940b44dSPeter Avalos 			"Literal pos bits (lp):         %" PRIu32 "\n"
1612940b44dSPeter Avalos 			"Number of pos bits (pb):       %" PRIu32 "\n",
1622940b44dSPeter Avalos 			(opt->dict_size + 512 * 1024) / (1024 * 1024),
1632940b44dSPeter Avalos 			my_log2(opt->dict_size), opt->lc, opt->lp, opt->pb);
1642940b44dSPeter Avalos 
1652940b44dSPeter Avalos 	free(opt);
1662940b44dSPeter Avalos 
1672940b44dSPeter Avalos 	return false;
1682940b44dSPeter Avalos }
1692940b44dSPeter Avalos 
1702940b44dSPeter Avalos 
1712940b44dSPeter Avalos extern int
main(int argc,char ** argv)1722940b44dSPeter Avalos main(int argc, char **argv)
1732940b44dSPeter Avalos {
1742940b44dSPeter Avalos 	tuklib_progname_init(argv);
1752940b44dSPeter Avalos 	tuklib_gettext_init(PACKAGE, LOCALEDIR);
1762940b44dSPeter Avalos 
1772940b44dSPeter Avalos 	parse_args(argc, argv);
1782940b44dSPeter Avalos 
1792940b44dSPeter Avalos #ifdef TUKLIB_DOSLIKE
1802940b44dSPeter Avalos 	setmode(fileno(stdin), O_BINARY);
1812940b44dSPeter Avalos #endif
1822940b44dSPeter Avalos 
1832940b44dSPeter Avalos 	int ret = EXIT_SUCCESS;
1842940b44dSPeter Avalos 
1852940b44dSPeter Avalos 	// We print empty lines around the output only when reading from
1862940b44dSPeter Avalos 	// files specified on the command line. This is due to how
1872940b44dSPeter Avalos 	// LZMA Utils did it.
1882940b44dSPeter Avalos 	if (optind == argc) {
1892940b44dSPeter Avalos 		if (lzmainfo("(stdin)", stdin))
1902940b44dSPeter Avalos 			ret = EXIT_FAILURE;
1912940b44dSPeter Avalos 	} else {
1922940b44dSPeter Avalos 		printf("\n");
1932940b44dSPeter Avalos 
1942940b44dSPeter Avalos 		do {
1952940b44dSPeter Avalos 			if (strcmp(argv[optind], "-") == 0) {
1962940b44dSPeter Avalos 				if (lzmainfo("(stdin)", stdin))
1972940b44dSPeter Avalos 					ret = EXIT_FAILURE;
1982940b44dSPeter Avalos 			} else {
1992940b44dSPeter Avalos 				FILE *f = fopen(argv[optind], "r");
2002940b44dSPeter Avalos 				if (f == NULL) {
2012940b44dSPeter Avalos 					ret = EXIT_FAILURE;
2022940b44dSPeter Avalos 					fprintf(stderr, "%s: %s: %s\n",
2032940b44dSPeter Avalos 							progname,
2042940b44dSPeter Avalos 							argv[optind],
2052940b44dSPeter Avalos 							strerror(errno));
2062940b44dSPeter Avalos 					continue;
2072940b44dSPeter Avalos 				}
2082940b44dSPeter Avalos 
2092940b44dSPeter Avalos 				if (lzmainfo(argv[optind], f))
2102940b44dSPeter Avalos 					ret = EXIT_FAILURE;
2112940b44dSPeter Avalos 
2122940b44dSPeter Avalos 				printf("\n");
2132940b44dSPeter Avalos 				fclose(f);
2142940b44dSPeter Avalos 			}
2152940b44dSPeter Avalos 		} while (++optind < argc);
2162940b44dSPeter Avalos 	}
2172940b44dSPeter Avalos 
2182940b44dSPeter Avalos 	tuklib_exit(ret, EXIT_FAILURE, true);
2192940b44dSPeter Avalos }
220