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 |