Rizin
unix-like reverse engineering framework and cli tools
lzmainfo.c
Go to the documentation of this file.
1 //
5 //
6 // Author: Lasse Collin
7 //
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
10 //
12 
13 #include "sysdefs.h"
14 #include <stdio.h>
15 #include <errno.h>
16 
17 #include "lzma.h"
18 #include "getopt.h"
19 #include "tuklib_gettext.h"
20 #include "tuklib_progname.h"
21 #include "tuklib_exit.h"
22 
23 #ifdef TUKLIB_DOSLIKE
24 # include <fcntl.h>
25 # include <io.h>
26 #endif
27 
28 
29 static void lzma_attribute((__noreturn__))
30 help(void)
31 {
32  printf(
33 _("Usage: %s [--help] [--version] [FILE]...\n"
34 "Show information stored in the .lzma file header"), progname);
35 
36  printf(_(
37 "\nWith no FILE, or when FILE is -, read standard input.\n"));
38  printf("\n");
39 
40  printf(_("Report bugs to <%s> (in English or Finnish).\n"),
42  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
43 
44  tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
45 }
46 
47 
48 static void lzma_attribute((__noreturn__))
49 version(void)
50 {
51  puts("lzmainfo (" PACKAGE_NAME ") " LZMA_VERSION_STRING);
52  tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
53 }
54 
55 
57 static void
58 parse_args(int argc, char **argv)
59 {
60  enum {
61  OPT_HELP,
62  OPT_VERSION,
63  };
64 
65  static const struct option long_opts[] = {
66  { "help", no_argument, NULL, OPT_HELP },
67  { "version", no_argument, NULL, OPT_VERSION },
68  { NULL, 0, NULL, 0 }
69  };
70 
71  int c;
72  while ((c = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
73  switch (c) {
74  case OPT_HELP:
75  help();
76 
77  case OPT_VERSION:
78  version();
79 
80  default:
81  exit(EXIT_FAILURE);
82  }
83  }
84 
85  return;
86 }
87 
88 
90 static uint32_t
92 {
93  uint32_t e;
94  for (e = 0; n > 1; ++e, n /= 2) ;
95  return e;
96 }
97 
98 
100 static bool
101 lzmainfo(const char *name, FILE *f)
102 {
103  uint8_t buf[13];
104  const size_t size = fread(buf, 1, sizeof(buf), f);
105  if (size != 13) {
106  fprintf(stderr, "%s: %s: %s\n", progname, name,
107  ferror(f) ? strerror(errno)
108  : _("File is too small to be a .lzma file"));
109  return true;
110  }
111 
113 
114  // Parse the first five bytes.
115  switch (lzma_properties_decode(&filter, NULL, buf, 5)) {
116  case LZMA_OK:
117  break;
118 
119  case LZMA_OPTIONS_ERROR:
120  fprintf(stderr, "%s: %s: %s\n", progname, name,
121  _("Not a .lzma file"));
122  return true;
123 
124  case LZMA_MEM_ERROR:
125  fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
126  exit(EXIT_FAILURE);
127 
128  default:
129  fprintf(stderr, "%s: %s\n", progname,
130  _("Internal error (bug)"));
131  exit(EXIT_FAILURE);
132  }
133 
134  // Uncompressed size
136  for (size_t i = 0; i < 8; ++i)
137  uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8);
138 
139  // Display the results. We don't want to translate these and also
140  // will use MB instead of MiB, because someone could be parsing
141  // this output and we don't want to break that when people move
142  // from LZMA Utils to XZ Utils.
143  if (f != stdin)
144  printf("%s\n", name);
145 
146  printf("Uncompressed size: ");
148  printf("Unknown");
149  else
150  printf("%" PRIu64 " MB (%" PRIu64 " bytes)",
151  (uncompressed_size + 512 * 1024)
152  / (1024 * 1024),
154 
155  lzma_options_lzma *opt = filter.options;
156 
157  printf("\nDictionary size: "
158  "%" PRIu32 " MB (2^%" PRIu32 " bytes)\n"
159  "Literal context bits (lc): %" PRIu32 "\n"
160  "Literal pos bits (lp): %" PRIu32 "\n"
161  "Number of pos bits (pb): %" PRIu32 "\n",
162  (opt->dict_size + 512 * 1024) / (1024 * 1024),
163  my_log2(opt->dict_size), opt->lc, opt->lp, opt->pb);
164 
165  free(opt);
166 
167  return false;
168 }
169 
170 
171 extern int
172 main(int argc, char **argv)
173 {
175  tuklib_gettext_init(PACKAGE, LOCALEDIR);
176 
177  parse_args(argc, argv);
178 
179 #ifdef TUKLIB_DOSLIKE
180  setmode(fileno(stdin), O_BINARY);
181 #endif
182 
183  int ret = EXIT_SUCCESS;
184 
185  // We print empty lines around the output only when reading from
186  // files specified on the command line. This is due to how
187  // LZMA Utils did it.
188  if (optind == argc) {
189  if (lzmainfo("(stdin)", stdin))
190  ret = EXIT_FAILURE;
191  } else {
192  printf("\n");
193 
194  do {
195  if (strcmp(argv[optind], "-") == 0) {
196  if (lzmainfo("(stdin)", stdin))
197  ret = EXIT_FAILURE;
198  } else {
199  FILE *f = fopen(argv[optind], "r");
200  if (f == NULL) {
201  ret = EXIT_FAILURE;
202  fprintf(stderr, "%s: %s: %s\n",
203  progname,
204  argv[optind],
205  strerror(errno));
206  continue;
207  }
208 
209  if (lzmainfo(argv[optind], f))
210  ret = EXIT_FAILURE;
211 
212  printf("\n");
213  fclose(f);
214  }
215  } while (++optind < argc);
216  }
217 
218  tuklib_exit(ret, EXIT_FAILURE, true);
219 }
static char * version
Definition: acr.h:4
#define e(frag)
lzma_index ** i
Definition: index.h:629
#define PACKAGE
Definition: config.h:59
#define PACKAGE_NAME
Definition: config.h:325
#define PACKAGE_BUGREPORT
Definition: config.h:322
#define PACKAGE_URL
Definition: config.h:334
int optind
Definition: getopt.h:6
#define O_BINARY
Definition: cpipe.c:13
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
#define no_argument
Definition: getopt.h:99
int getopt_long()
#define PRIu32
Definition: macros.h:20
#define PRIu64
Definition: macros.h:18
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
#define LZMA_FILTER_LZMA1
LZMA1 Filter ID.
Definition: lzma12.h:30
The public API of liblzma data compression library.
static void lzma_attribute((__noreturn__))
Definition: lzmainfo.c:29
int main(int argc, char **argv)
Definition: lzmainfo.c:172
static bool lzmainfo(const char *name, FILE *f)
Parse the .lzma header and display information about it.
Definition: lzmainfo.c:101
static void parse_args(int argc, char **argv)
Parse command line options.
Definition: lzmainfo.c:58
static uint32_t my_log2(uint32_t n)
Primitive base-2 logarithm for integers.
Definition: lzmainfo.c:91
int n
Definition: mipsasm.c:19
string FILE
Definition: benchmark.py:21
#define _(String)
Definition: opintl.h:53
unsigned int uint32_t
Definition: sftypes.h:29
#define ENOMEM
Definition: sftypes.h:122
unsigned long uint64_t
Definition: sftypes.h:28
unsigned char uint8_t
Definition: sftypes.h:31
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define UINT64_MAX
Filter options.
Definition: filter.h:43
Options specific to the LZMA1 and LZMA2 filters.
Definition: lzma12.h:185
uint32_t lp
Number of literal position bits.
Definition: lzma12.h:293
uint32_t lc
Number of literal context bits.
Definition: lzma12.h:281
uint32_t pb
Number of position bits.
Definition: lzma12.h:316
uint32_t dict_size
Dictionary size in bytes.
Definition: lzma12.h:217
Definition: z80asm.h:102
Definition: getopt.h:84
uint64_t uncompressed_size
Definition: list.c:106
Common includes, definitions, system-specific things etc.
Close stdout and stderr, and exit.
#define tuklib_exit
Definition: tuklib_exit.h:20
Wrapper for gettext and friends.
#define tuklib_gettext_init(package, localedir)
Program name to be displayed in messages.
#define progname
#define tuklib_progname_init
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128
@ LZMA_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
#define LZMA_VERSION_STRING
Compile-time version as a string.
Definition: version.h:92