| Index: xz/src/lzmainfo/lzmainfo.c
|
| ===================================================================
|
| --- xz/src/lzmainfo/lzmainfo.c (revision 0)
|
| +++ xz/src/lzmainfo/lzmainfo.c (revision 0)
|
| @@ -0,0 +1,210 @@
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +//
|
| +/// \file lzmainfo.c
|
| +/// \brief lzmainfo tool for compatibility with LZMA Utils
|
| +//
|
| +// Author: Lasse Collin
|
| +//
|
| +// This file has been put into the public domain.
|
| +// You can do whatever you want with this file.
|
| +//
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +
|
| +#include "sysdefs.h"
|
| +#include <stdio.h>
|
| +#include <errno.h>
|
| +
|
| +#include "lzma.h"
|
| +#include "getopt.h"
|
| +#include "tuklib_gettext.h"
|
| +#include "tuklib_progname.h"
|
| +#include "tuklib_exit.h"
|
| +
|
| +
|
| +static void lzma_attribute((noreturn))
|
| +help(void)
|
| +{
|
| + printf(
|
| +_("Usage: %s [--help] [--version] [FILE]...\n"
|
| +"Show information stored in the .lzma file header"), progname);
|
| +
|
| + printf(_(
|
| +"\nWith no FILE, or when FILE is -, read standard input.\n"));
|
| + printf("\n");
|
| +
|
| + printf(_("Report bugs to <%s> (in English or Finnish).\n"),
|
| + PACKAGE_BUGREPORT);
|
| + printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
|
| +
|
| + tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
|
| +}
|
| +
|
| +
|
| +static void lzma_attribute((noreturn))
|
| +version(void)
|
| +{
|
| + puts("lzmainfo (" PACKAGE_NAME ") " PACKAGE_VERSION);
|
| + tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
|
| +}
|
| +
|
| +
|
| +/// Parse command line options.
|
| +static void
|
| +parse_args(int argc, char **argv)
|
| +{
|
| + enum {
|
| + OPT_HELP,
|
| + OPT_VERSION,
|
| + };
|
| +
|
| + static const struct option long_opts[] = {
|
| + { "help", no_argument, NULL, OPT_HELP },
|
| + { "version", no_argument, NULL, OPT_VERSION },
|
| + { NULL, 0, NULL, 0 }
|
| + };
|
| +
|
| + int c;
|
| + while ((c = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
| + switch (c) {
|
| + case OPT_HELP:
|
| + help();
|
| +
|
| + case OPT_VERSION:
|
| + version();
|
| +
|
| + default:
|
| + exit(EXIT_FAILURE);
|
| + }
|
| + }
|
| +
|
| + return;
|
| +}
|
| +
|
| +
|
| +/// Primitive base-2 logarithm for integers
|
| +static uint32_t
|
| +my_log2(uint32_t n)
|
| +{
|
| + uint32_t e;
|
| + for (e = 0; n > 1; ++e, n /= 2) ;
|
| + return e;
|
| +}
|
| +
|
| +
|
| +/// Parse the .lzma header and display information about it.
|
| +static bool
|
| +lzmainfo(const char *name, FILE *f)
|
| +{
|
| + uint8_t buf[13];
|
| + const size_t size = fread(buf, 1, sizeof(buf), f);
|
| + if (size != 13) {
|
| + fprintf(stderr, "%s: %s: %s\n", progname, name,
|
| + ferror(f) ? strerror(errno)
|
| + : _("File is too small to be a .lzma file"));
|
| + return true;
|
| + }
|
| +
|
| + lzma_filter filter = { .id = LZMA_FILTER_LZMA1 };
|
| +
|
| + // Parse the first five bytes.
|
| + switch (lzma_properties_decode(&filter, NULL, buf, 5)) {
|
| + case LZMA_OK:
|
| + break;
|
| +
|
| + case LZMA_OPTIONS_ERROR:
|
| + fprintf(stderr, "%s: %s: %s\n", progname, name,
|
| + _("Not a .lzma file"));
|
| + return true;
|
| +
|
| + case LZMA_MEM_ERROR:
|
| + fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
|
| + exit(EXIT_FAILURE);
|
| +
|
| + default:
|
| + fprintf(stderr, "%s: %s\n", progname,
|
| + _("Internal error (bug)"));
|
| + exit(EXIT_FAILURE);
|
| + }
|
| +
|
| + // Uncompressed size
|
| + uint64_t uncompressed_size = 0;
|
| + for (size_t i = 0; i < 8; ++i)
|
| + uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8);
|
| +
|
| + // Display the results. We don't want to translate these and also
|
| + // will use MB instead of MiB, because someone could be parsing
|
| + // this output and we don't want to break that when people move
|
| + // from LZMA Utils to XZ Utils.
|
| + if (f != stdin)
|
| + printf("%s\n", name);
|
| +
|
| + printf("Uncompressed size: ");
|
| + if (uncompressed_size == UINT64_MAX)
|
| + printf("Unknown");
|
| + else
|
| + printf("%" PRIu64 " MB (%" PRIu64 " bytes)",
|
| + (uncompressed_size + 512 * 1024)
|
| + / (1024 * 1024),
|
| + uncompressed_size);
|
| +
|
| + lzma_options_lzma *opt = filter.options;
|
| +
|
| + printf("\nDictionary size: "
|
| + "%u MB (2^%u bytes)\n"
|
| + "Literal context bits (lc): %" PRIu32 "\n"
|
| + "Literal pos bits (lp): %" PRIu32 "\n"
|
| + "Number of pos bits (pb): %" PRIu32 "\n",
|
| + (opt->dict_size + 512 * 1024) / (1024 * 1024),
|
| + my_log2(opt->dict_size), opt->lc, opt->lp, opt->pb);
|
| +
|
| + free(opt);
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| +extern int
|
| +main(int argc, char **argv)
|
| +{
|
| + tuklib_progname_init(argv);
|
| + tuklib_gettext_init(PACKAGE, LOCALEDIR);
|
| +
|
| + parse_args(argc, argv);
|
| +
|
| + int ret = EXIT_SUCCESS;
|
| +
|
| + // We print empty lines around the output only when reading from
|
| + // files specified on the command line. This is due to how
|
| + // LZMA Utils did it.
|
| + if (optind == argc) {
|
| + if (lzmainfo("(stdin)", stdin))
|
| + ret = EXIT_FAILURE;
|
| + } else {
|
| + printf("\n");
|
| +
|
| + do {
|
| + if (strcmp(argv[optind], "-") == 0) {
|
| + if (lzmainfo("(stdin)", stdin))
|
| + ret = EXIT_FAILURE;
|
| + } else {
|
| + FILE *f = fopen(argv[optind], "r");
|
| + if (f == NULL) {
|
| + ret = EXIT_FAILURE;
|
| + fprintf(stderr, "%s: %s: %s\n",
|
| + progname,
|
| + argv[optind],
|
| + strerror(errno));
|
| + continue;
|
| + }
|
| +
|
| + if (lzmainfo(argv[optind], f))
|
| + ret = EXIT_FAILURE;
|
| +
|
| + printf("\n");
|
| + fclose(f);
|
| + }
|
| + } while (++optind < argc);
|
| + }
|
| +
|
| + tuklib_exit(ret, EXIT_FAILURE, true);
|
| +}
|
|
|
| Property changes on: xz/src/lzmainfo/lzmainfo.c
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|