Rizin
unix-like reverse engineering framework and cli tools
list.c File Reference

Listing information about .xz files. More...

#include "private.h"
#include "tuklib_integer.h"

Go to the source code of this file.

Classes

struct  xz_file_info
 Information about a .xz file. More...
 
struct  block_header_info
 Information about a .xz Block. More...
 

Macros

#define XZ_FILE_INFO_INIT   { NULL, 0, 0, true, 50000002 }
 
#define CHECKS_STR_SIZE   1024
 

Functions

static const char * xz_ver_to_str (uint32_t ver)
 Convert XZ Utils version number to a string. More...
 
static bool parse_indexes (xz_file_info *xfi, file_pair *pair)
 Parse the Index(es) from the given .xz file. More...
 
static bool parse_block_header (file_pair *pair, const lzma_index_iter *iter, block_header_info *bhi, xz_file_info *xfi)
 Parse the Block Header. More...
 
static bool parse_check_value (file_pair *pair, const lzma_index_iter *iter)
 Parse the Check field and put it into check_value[]. More...
 
static bool parse_details (file_pair *pair, const lzma_index_iter *iter, block_header_info *bhi, xz_file_info *xfi)
 Parse detailed information about a Block. More...
 
static const char * get_ratio (uint64_t compressed_size, uint64_t uncompressed_size)
 Get the compression ratio. More...
 
static void get_check_names (char buf[CHECKS_STR_SIZE], uint32_t checks, bool space_after_comma)
 Get a comma-separated list of Check names. More...
 
static bool print_info_basic (const xz_file_info *xfi, file_pair *pair)
 
static void print_adv_helper (uint64_t stream_count, uint64_t block_count, uint64_t compressed_size, uint64_t uncompressed_size, uint32_t checks, uint64_t stream_padding)
 
static bool print_info_adv (xz_file_info *xfi, file_pair *pair)
 
static bool print_info_robot (xz_file_info *xfi, file_pair *pair)
 
static void update_totals (const xz_file_info *xfi)
 
static void print_totals_basic (void)
 
static void print_totals_adv (void)
 
static void print_totals_robot (void)
 
void list_totals (void)
 Show the totals after all files have been listed. More...
 
void list_file (const char *filename)
 List information about the given .xz file. More...
 

Variables

static const char check_names [LZMA_CHECK_ID_MAX+1][12]
 Check ID to string mapping. More...
 
static char check_value [2 *LZMA_CHECK_SIZE_MAX+1]
 
struct {
   uint64_t   files
 
   uint64_t   streams
 
   uint64_t   blocks
 
   uint64_t   compressed_size
 
   uint64_t   uncompressed_size
 
   uint64_t   stream_padding
 
   uint64_t   memusage_max
 
   uint32_t   checks
 
   uint32_t   min_version
 
   bool   all_have_sizes
 
totals = { 0, 0, 0, 0, 0, 0, 0, 0, 50000002, true }
 

Detailed Description

Listing information about .xz files.

Definition in file list.c.

Macro Definition Documentation

◆ CHECKS_STR_SIZE

#define CHECKS_STR_SIZE   1024

Buffer size for get_check_names(). This may be a bit ridiculous, but at least it's enough if some language needs many multibyte chars.

Definition at line 90 of file list.c.

◆ XZ_FILE_INFO_INIT

#define XZ_FILE_INFO_INIT   { NULL, 0, 0, true, 50000002 }

Definition at line 37 of file list.c.

Function Documentation

◆ get_check_names()

static void get_check_names ( char  buf[CHECKS_STR_SIZE],
uint32_t  checks,
bool  space_after_comma 
)
static

Get a comma-separated list of Check names.

The check names are translated with gettext except when in robot mode.

Parameters
bufBuffer to hold the resulting string
checksBit mask of Checks to print
space_after_commaIt's better to not use spaces in table-like listings, but in more verbose formats a space after a comma is good for readability.

Definition at line 638 of file list.c.

640 {
641  // If we get called when there are no Checks to print, set checks
642  // to 1 so that we print "None". This can happen in the robot mode
643  // when printing the totals line if there are no valid input files.
644  if (checks == 0)
645  checks = 1;
646 
647  char *pos = buf;
648  size_t left = CHECKS_STR_SIZE;
649 
650  const char *sep = space_after_comma ? ", " : ",";
651  bool comma = false;
652 
653  for (size_t i = 0; i <= LZMA_CHECK_ID_MAX; ++i) {
654  if (checks & (UINT32_C(1) << i)) {
655  my_snprintf(&pos, &left, "%s%s",
656  comma ? sep : "",
658  : _(check_names[i]));
659  comma = true;
660  }
661  }
662 
663  return;
664 }
#define LZMA_CHECK_ID_MAX
Maximum valid Check ID.
Definition: check.h:68
lzma_index ** i
Definition: index.h:629
bool opt_robot
Definition: args.c:24
voidpf void * buf
Definition: ioapi.h:138
#define _(String)
Definition: opintl.h:53
#define UINT32_C(val)
int pos
Definition: main.c:11
#define CHECKS_STR_SIZE
Definition: list.c:90
static const char check_names[LZMA_CHECK_ID_MAX+1][12]
Check ID to string mapping.
Definition: list.c:61
uint32_t checks
Definition: list.c:109
void my_snprintf(char **pos, size_t *left, const char *fmt,...)
Definition: util.c:239
static int comma
Definition: z80asm.c:76

References _, check_names, checks, CHECKS_STR_SIZE, comma, i, LZMA_CHECK_ID_MAX, my_snprintf(), opt_robot, pos, and UINT32_C.

Referenced by print_adv_helper(), print_info_basic(), print_info_robot(), print_totals_basic(), and print_totals_robot().

◆ get_ratio()

static const char* get_ratio ( uint64_t  compressed_size,
uint64_t  uncompressed_size 
)
static

Get the compression ratio.

This has slightly different format than that is used in message.c.

Definition at line 611 of file list.c.

612 {
613  if (uncompressed_size == 0)
614  return "---";
615 
616  const double ratio = (double)(compressed_size)
617  / (double)(uncompressed_size);
618  if (ratio > 9.999)
619  return "---";
620 
621  static char buf[16];
622  snprintf(buf, sizeof(buf), "%.3f", ratio);
623  return buf;
624 }
snprintf
Definition: kernel.h:364
uint64_t compressed_size
Definition: list.c:105
uint64_t uncompressed_size
Definition: list.c:106

References compressed_size, snprintf, and uncompressed_size.

Referenced by print_adv_helper(), print_info_adv(), print_info_basic(), print_info_robot(), print_totals_basic(), and print_totals_robot().

◆ list_file()

void list_file ( const char *  filename)

List information about the given .xz file.

Definition at line 1143 of file list.c.

1144 {
1146  message_fatal(_("--list works only on .xz files "
1147  "(--format=xz or --format=auto)"));
1148 
1150 
1151  if (filename == stdin_filename) {
1152  message_error(_("--list does not support reading from "
1153  "standard input"));
1154  return;
1155  }
1156 
1157  // Unset opt_stdout so that io_open_src() won't accept special files.
1158  // Set opt_force so that io_open_src() will follow symlinks.
1159  opt_stdout = false;
1160  opt_force = true;
1161  file_pair *pair = io_open_src(filename);
1162  if (pair == NULL)
1163  return;
1164 
1166  if (!parse_indexes(&xfi, pair)) {
1167  bool fail;
1168 
1169  // We have three main modes:
1170  // - --robot, which has submodes if --verbose is specified
1171  // once or twice
1172  // - Normal --list without --verbose
1173  // - --list with one or two --verbose
1174  if (opt_robot)
1175  fail = print_info_robot(&xfi, pair);
1176  else if (message_verbosity_get() <= V_WARNING)
1177  fail = print_info_basic(&xfi, pair);
1178  else
1179  fail = print_info_adv(&xfi, pair);
1180 
1181  // Update the totals that are displayed after all
1182  // the individual files have been listed. Don't count
1183  // broken files.
1184  if (!fail)
1185  update_totals(&xfi);
1186 
1187  lzma_index_end(xfi.idx, NULL);
1188  }
1189 
1190  io_close(pair, false);
1191  return;
1192 }
const char stdin_filename[]
Definition: args.c:29
bool opt_stdout
Definition: args.c:21
bool opt_force
Definition: args.c:22
enum format_type opt_format
Definition: coder.c:25
@ FORMAT_AUTO
Definition: coder.h:23
@ FORMAT_XZ
Definition: coder.h:24
#define NULL
Definition: cris-opc.c:27
void io_close(file_pair *pair, bool success)
Closes the file descriptors and frees possible allocated memory.
Definition: file_io.c:1052
file_pair * io_open_src(const char *src_name)
Open the source file.
Definition: file_io.c:741
const char * filename
Definition: ioapi.h:137
void message_filename(const char *src_name)
Set the name of the current file and possibly print it too.
Definition: message.c:232
void message_error(const char *fmt,...)
Definition: message.c:764
void message_fatal(const char *fmt,...)
Definition: message.c:777
enum message_verbosity message_verbosity_get(void)
Get the current verbosity level.
Definition: message.c:181
@ V_WARNING
Errors and warnings.
Definition: message.h:17
Information about a .xz file.
Definition: list.c:18
lzma_index * idx
Combined Index of all Streams in the file.
Definition: list.c:20
static bool print_info_robot(xz_file_info *xfi, file_pair *pair)
Definition: list.c:916
static void update_totals(const xz_file_info *xfi)
Definition: list.c:1001
static bool print_info_adv(xz_file_info *xfi, file_pair *pair)
Definition: list.c:738
static bool print_info_basic(const xz_file_info *xfi, file_pair *pair)
Definition: list.c:668
#define XZ_FILE_INFO_INIT
Definition: list.c:37
static bool parse_indexes(xz_file_info *xfi, file_pair *pair)
Parse the Index(es) from the given .xz file.
Definition: list.c:150
#define fail(test)
Definition: tests.h:29

References _, fail, FORMAT_AUTO, FORMAT_XZ, xz_file_info::idx, io_close(), io_open_src(), message_error(), message_fatal(), message_filename(), message_verbosity_get(), NULL, opt_force, opt_format, opt_robot, opt_stdout, parse_indexes(), print_info_adv(), print_info_basic(), print_info_robot(), stdin_filename, update_totals(), V_WARNING, and XZ_FILE_INFO_INIT.

Referenced by main().

◆ list_totals()

void list_totals ( void  )

Show the totals after all files have been listed.

Definition at line 1121 of file list.c.

1122 {
1123  if (opt_robot) {
1124  // Always print totals in --robot mode. It can be convenient
1125  // in some cases and doesn't complicate usage of the
1126  // single-file case much.
1128 
1129  } else if (totals.files > 1) {
1130  // For non-robot mode, totals are printed only if there
1131  // is more than one file.
1134  else
1135  print_totals_adv();
1136  }
1137 
1138  return;
1139 }
static struct @659 totals
static void print_totals_basic(void)
Definition: list.c:1025
static void print_totals_robot(void)
Definition: list.c:1091
static void print_totals_adv(void)
Definition: list.c:1067

References message_verbosity_get(), opt_robot, print_totals_adv(), print_totals_basic(), print_totals_robot(), totals, and V_WARNING.

Referenced by main().

◆ parse_block_header()

static bool parse_block_header ( file_pair pair,
const lzma_index_iter iter,
block_header_info bhi,
xz_file_info xfi 
)
static

Parse the Block Header.

The result is stored into *bhi. The caller takes care of initializing it.

Returns
False on success, true on error.

Definition at line 406 of file list.c.

408 {
409 #if IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
410 # error IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
411 #endif
412 
413  // Get the whole Block Header with one read, but don't read past
414  // the end of the Block (or even its Check field).
415  const uint32_t size = my_min(iter->block.total_size
416  - lzma_check_size(iter->stream.flags->check),
418  io_buf buf;
419  if (io_pread(pair, &buf, size, iter->block.compressed_file_offset))
420  return true;
421 
422  // Zero would mean Index Indicator and thus not a valid Block.
423  if (buf.u8[0] == 0)
424  goto data_error;
425 
426  // Initialize the block structure and decode Block Header Size.
428  lzma_block block;
429  block.version = 0;
430  block.check = iter->stream.flags->check;
431  block.filters = filters;
432 
434  if (block.header_size > size)
435  goto data_error;
436 
437  // Decode the Block Header.
438  switch (lzma_block_header_decode(&block, NULL, buf.u8)) {
439  case LZMA_OK:
440  break;
441 
442  case LZMA_OPTIONS_ERROR:
443  message_error("%s: %s", pair->src_name,
445  return true;
446 
447  case LZMA_DATA_ERROR:
448  goto data_error;
449 
450  default:
451  message_bug();
452  }
453 
454  // Check the Block Flags. These must be done before calling
455  // lzma_block_compressed_size(), because it overwrites
456  // block.compressed_size.
457  bhi->flags[0] = block.compressed_size != LZMA_VLI_UNKNOWN
458  ? 'c' : '-';
459  bhi->flags[1] = block.uncompressed_size != LZMA_VLI_UNKNOWN
460  ? 'u' : '-';
461  bhi->flags[2] = '\0';
462 
463  // Collect information if all Blocks have both Compressed Size
464  // and Uncompressed Size fields. They can be useful e.g. for
465  // multi-threaded decompression so it can be useful to know it.
468 
469  // Validate or set block.compressed_size.
470  switch (lzma_block_compressed_size(&block,
471  iter->block.unpadded_size)) {
472  case LZMA_OK:
473  // Validate also block.uncompressed_size if it is present.
474  // If it isn't present, there's no need to set it since
475  // we aren't going to actually decompress the Block; if
476  // we were decompressing, then we should set it so that
477  // the Block decoder could validate the Uncompressed Size
478  // that was stored in the Index.
480  || block.uncompressed_size
481  == iter->block.uncompressed_size)
482  break;
483 
484  // If the above fails, the file is corrupt so
485  // LZMA_DATA_ERROR is a good error code.
486 
487  // Fall through
488 
489  case LZMA_DATA_ERROR:
490  // Free the memory allocated by lzma_block_header_decode().
491  for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
492  free(filters[i].options);
493 
494  goto data_error;
495 
496  default:
497  message_bug();
498  }
499 
500  // Copy the known sizes.
501  bhi->header_size = block.header_size;
502  bhi->compressed_size = block.compressed_size;
503 
504  // Calculate the decoder memory usage and update the maximum
505  // memory usage of this Block.
506  bhi->memusage = lzma_raw_decoder_memusage(filters);
507  if (xfi->memusage_max < bhi->memusage)
508  xfi->memusage_max = bhi->memusage;
509 
510  // Determine the minimum XZ Utils version that supports this Block.
511  //
512  // Currently the only thing that 5.0.0 doesn't support is empty
513  // LZMA2 Block. This decoder bug was fixed in 5.0.2.
514  {
515  size_t i = 0;
516  while (filters[i + 1].id != LZMA_VLI_UNKNOWN)
517  ++i;
518 
519  if (filters[i].id == LZMA_FILTER_LZMA2
520  && iter->block.uncompressed_size == 0
521  && xfi->min_version < 50000022U)
522  xfi->min_version = 50000022U;
523  }
524 
525  // Convert the filter chain to human readable form.
527 
528  // Free the memory allocated by lzma_block_header_decode().
529  for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
530  free(filters[i].options);
531 
532  return false;
533 
534 data_error:
535  // Show the error message.
536  message_error("%s: %s", pair->src_name,
538  return true;
539 }
#define lzma_block_header_size_decode(b)
Decode the Block Header Size field.
Definition: block.h:285
#define LZMA_BLOCK_HEADER_SIZE_MAX
Definition: block.h:74
const lzma_filter * filters
Definition: container.h:315
bool io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos)
Read from source file from given offset to a buffer.
Definition: file_io.c:1186
#define LZMA_FILTERS_MAX
Maximum number of filters in a chain.
Definition: filter.h:26
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
#define LZMA_FILTER_LZMA2
LZMA2 Filter ID.
Definition: lzma12.h:40
void message_bug(void)
Definition: message.c:789
void message_filters_to_str(char buf[FILTERS_STR_SIZE], const lzma_filter *filters, bool all_known)
Get the filter chain as a string.
Definition: message.c:917
const char * message_strm(lzma_ret code)
Convert lzma_ret to a string.
Definition: message.c:803
unsigned int uint32_t
Definition: sftypes.h:29
char filter_chain[FILTERS_STR_SIZE]
The filter chain of this Block in human-readable form.
Definition: list.c:55
uint32_t header_size
Size of the Block Header.
Definition: list.c:43
uint64_t memusage
Decoder memory usage for this Block.
Definition: list.c:52
lzma_vli compressed_size
Size of the Compressed Data field in the Block.
Definition: list.c:49
char flags[3]
A few of the Block Flags as a string.
Definition: list.c:46
const char * src_name
Definition: file_io.h:37
Options for the Block and Block Header encoders and decoders.
Definition: block.h:30
lzma_vli uncompressed_size
Uncompressed Size in bytes.
Definition: block.h:172
lzma_filter * filters
Array of filters.
Definition: block.h:200
uint32_t header_size
Size of the Block Header field.
Definition: block.h:72
lzma_check check
Type of integrity Check.
Definition: block.h:93
lzma_vli compressed_size
Size of the Compressed Data in bytes.
Definition: block.h:148
uint32_t version
Block format version.
Definition: block.h:52
Filter options.
Definition: filter.h:43
lzma_vli id
Filter ID.
Definition: filter.h:54
uint32_t min_version
Oldest XZ Utils version that will decompress the file.
Definition: list.c:33
bool all_have_sizes
Definition: list.c:30
uint64_t memusage_max
Highest memory usage so far.
Definition: list.c:26
#define my_min(x, y)
Definition: sysdefs.h:185
Definition: file_io.h:27
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39
@ LZMA_DATA_ERROR
Data is corrupt.
Definition: base.h:172
@ LZMA_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58

References xz_file_info::all_have_sizes, lzma_block::check, lzma_block::compressed_size, block_header_info::compressed_size, block_header_info::filter_chain, lzma_block::filters, filters, block_header_info::flags, free(), lzma_block::header_size, block_header_info::header_size, i, lzma_filter::id, io_pread(), lzma_block_header_size_decode, LZMA_BLOCK_HEADER_SIZE_MAX, LZMA_DATA_ERROR, LZMA_FILTER_LZMA2, LZMA_FILTERS_MAX, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_VLI_UNKNOWN, block_header_info::memusage, xz_file_info::memusage_max, message_bug(), message_error(), message_filters_to_str(), message_strm(), xz_file_info::min_version, my_min, NULL, options, file_pair::src_name, lzma_block::uncompressed_size, and lzma_block::version.

Referenced by parse_details().

◆ parse_check_value()

static bool parse_check_value ( file_pair pair,
const lzma_index_iter iter 
)
static

Parse the Check field and put it into check_value[].

Returns
False on success, true on error.

Definition at line 546 of file list.c.

547 {
548  // Don't read anything from the file if there is no integrity Check.
549  if (iter->stream.flags->check == LZMA_CHECK_NONE) {
550  snprintf(check_value, sizeof(check_value), "---");
551  return false;
552  }
553 
554  // Locate and read the Check field.
555  const uint32_t size = lzma_check_size(iter->stream.flags->check);
556  const off_t offset = iter->block.compressed_file_offset
557  + iter->block.total_size - size;
558  io_buf buf;
559  if (io_pread(pair, &buf, size, offset))
560  return true;
561 
562  // CRC32 and CRC64 are in little endian. Guess that all the future
563  // 32-bit and 64-bit Check values are little endian too. It shouldn't
564  // be a too big problem if this guess is wrong.
565  if (size == 4)
567  "%08" PRIx32, conv32le(buf.u32[0]));
568  else if (size == 8)
570  "%016" PRIx64, conv64le(buf.u64[0]));
571  else
572  for (size_t i = 0; i < size; ++i)
573  snprintf(check_value + i * 2, 3, "%02x", buf.u8[i]);
574 
575  return false;
576 }
@ LZMA_CHECK_NONE
Definition: check.h:28
voidpf uLong offset
Definition: ioapi.h:144
int off_t
Definition: sftypes.h:41
static char check_value[2 *LZMA_CHECK_SIZE_MAX+1]
Definition: list.c:95
#define PRIx32
Definition: sysdefs.h:67
#define PRIx64
Definition: sysdefs.h:94
#define conv64le(num)
#define conv32le(num)

References check_value, conv32le, conv64le, i, io_pread(), LZMA_CHECK_NONE, PRIx32, PRIx64, and snprintf.

Referenced by parse_details().

◆ parse_details()

static bool parse_details ( file_pair pair,
const lzma_index_iter iter,
block_header_info bhi,
xz_file_info xfi 
)
static

Parse detailed information about a Block.

Since this requires seek(s), listing information about all Blocks can be slow.

Parameters
pairInput file
iterLocation of the Block whose Check value should be printed.
bhiPointer to structure where to store the information about the Block Header field.
Returns
False on success, true on error. If an error occurs, the error message is printed too so the caller doesn't need to worry about that.

Definition at line 594 of file list.c.

596 {
597  if (parse_block_header(pair, iter, bhi, xfi))
598  return true;
599 
600  if (parse_check_value(pair, iter))
601  return true;
602 
603  return false;
604 }
static bool parse_check_value(file_pair *pair, const lzma_index_iter *iter)
Parse the Check field and put it into check_value[].
Definition: list.c:546
static bool parse_block_header(file_pair *pair, const lzma_index_iter *iter, block_header_info *bhi, xz_file_info *xfi)
Parse the Block Header.
Definition: list.c:406

References parse_block_header(), and parse_check_value().

Referenced by print_info_adv(), and print_info_robot().

◆ parse_indexes()

static bool parse_indexes ( xz_file_info xfi,
file_pair pair 
)
static

Parse the Index(es) from the given .xz file.

Parameters
xfiPointer to structure where the decoded information is stored.
pairInput file
Returns
On success, false is returned. On error, true is returned.

Definition at line 150 of file list.c.

151 {
152  if (pair->src_st.st_size <= 0) {
153  message_error(_("%s: File is empty"), pair->src_name);
154  return true;
155  }
156 
157  if (pair->src_st.st_size < 2 * LZMA_STREAM_HEADER_SIZE) {
158  message_error(_("%s: Too small to be a valid .xz file"),
159  pair->src_name);
160  return true;
161  }
162 
163  io_buf buf;
164  lzma_stream_flags header_flags;
165  lzma_stream_flags footer_flags;
166  lzma_ret ret;
167 
168  // lzma_stream for the Index decoder
170 
171  // All Indexes decoded so far
172  lzma_index *combined_index = NULL;
173 
174  // The Index currently being decoded
175  lzma_index *this_index = NULL;
176 
177  // Current position in the file. We parse the file backwards so
178  // initialize it to point to the end of the file.
179  off_t pos = pair->src_st.st_size;
180 
181  // Each loop iteration decodes one Index.
182  do {
183  // Check that there is enough data left to contain at least
184  // the Stream Header and Stream Footer. This check cannot
185  // fail in the first pass of this loop.
186  if (pos < 2 * LZMA_STREAM_HEADER_SIZE) {
187  message_error("%s: %s", pair->src_name,
189  goto error;
190  }
191 
194 
195  // Locate the Stream Footer. There may be Stream Padding which
196  // we must skip when reading backwards.
197  while (true) {
199  message_error("%s: %s", pair->src_name,
200  message_strm(
201  LZMA_DATA_ERROR));
202  goto error;
203  }
204 
205  if (io_pread(pair, &buf,
207  goto error;
208 
209  // Stream Padding is always a multiple of four bytes.
210  int i = 2;
211  if (buf.u32[i] != 0)
212  break;
213 
214  // To avoid calling io_pread() for every four bytes
215  // of Stream Padding, take advantage that we read
216  // 12 bytes (LZMA_STREAM_HEADER_SIZE) already and
217  // check them too before calling io_pread() again.
218  do {
219  stream_padding += 4;
220  pos -= 4;
221  --i;
222  } while (i >= 0 && buf.u32[i] == 0);
223  }
224 
225  // Decode the Stream Footer.
226  ret = lzma_stream_footer_decode(&footer_flags, buf.u8);
227  if (ret != LZMA_OK) {
228  message_error("%s: %s", pair->src_name,
229  message_strm(ret));
230  goto error;
231  }
232 
233  // Check that the Stream Footer doesn't specify something
234  // that we don't support. This can only happen if the xz
235  // version is older than liblzma and liblzma supports
236  // something new.
237  //
238  // It is enough to check Stream Footer. Stream Header must
239  // match when it is compared against Stream Footer with
240  // lzma_stream_flags_compare().
241  if (footer_flags.version != 0) {
242  message_error("%s: %s", pair->src_name,
244  goto error;
245  }
246 
247  // Check that the size of the Index field looks sane.
248  lzma_vli index_size = footer_flags.backward_size;
250  message_error("%s: %s", pair->src_name,
252  goto error;
253  }
254 
255  // Set pos to the beginning of the Index.
256  pos -= index_size;
257 
258  // See how much memory we can use for decoding this Index.
260  uint64_t memused = 0;
261  if (combined_index != NULL) {
262  memused = lzma_index_memused(combined_index);
263  if (memused > memlimit)
264  message_bug();
265 
266  memlimit -= memused;
267  }
268 
269  // Decode the Index.
270  ret = lzma_index_decoder(&strm, &this_index, memlimit);
271  if (ret != LZMA_OK) {
272  message_error("%s: %s", pair->src_name,
273  message_strm(ret));
274  goto error;
275  }
276 
277  do {
278  // Don't give the decoder more input than the
279  // Index size.
281  if (io_pread(pair, &buf, strm.avail_in, pos))
282  goto error;
283 
284  pos += strm.avail_in;
286 
287  strm.next_in = buf.u8;
288  ret = lzma_code(&strm, LZMA_RUN);
289 
290  } while (ret == LZMA_OK);
291 
292  // If the decoding seems to be successful, check also that
293  // the Index decoder consumed as much input as indicated
294  // by the Backward Size field.
295  if (ret == LZMA_STREAM_END)
296  if (index_size != 0 || strm.avail_in != 0)
297  ret = LZMA_DATA_ERROR;
298 
299  if (ret != LZMA_STREAM_END) {
300  // LZMA_BUFFER_ERROR means that the Index decoder
301  // would have liked more input than what the Index
302  // size should be according to Stream Footer.
303  // The message for LZMA_DATA_ERROR makes more
304  // sense in that case.
305  if (ret == LZMA_BUF_ERROR)
306  ret = LZMA_DATA_ERROR;
307 
308  message_error("%s: %s", pair->src_name,
309  message_strm(ret));
310 
311  // If the error was too low memory usage limit,
312  // show also how much memory would have been needed.
313  if (ret == LZMA_MEMLIMIT_ERROR) {
314  uint64_t needed = lzma_memusage(&strm);
315  if (UINT64_MAX - needed < memused)
316  needed = UINT64_MAX;
317  else
318  needed += memused;
319 
320  message_mem_needed(V_ERROR, needed);
321  }
322 
323  goto error;
324  }
325 
326  // Decode the Stream Header and check that its Stream Flags
327  // match the Stream Footer.
328  pos -= footer_flags.backward_size + LZMA_STREAM_HEADER_SIZE;
329  if ((lzma_vli)(pos) < lzma_index_total_size(this_index)) {
330  message_error("%s: %s", pair->src_name,
332  goto error;
333  }
334 
335  pos -= lzma_index_total_size(this_index);
336  if (io_pread(pair, &buf, LZMA_STREAM_HEADER_SIZE, pos))
337  goto error;
338 
339  ret = lzma_stream_header_decode(&header_flags, buf.u8);
340  if (ret != LZMA_OK) {
341  message_error("%s: %s", pair->src_name,
342  message_strm(ret));
343  goto error;
344  }
345 
346  ret = lzma_stream_flags_compare(&header_flags, &footer_flags);
347  if (ret != LZMA_OK) {
348  message_error("%s: %s", pair->src_name,
349  message_strm(ret));
350  goto error;
351  }
352 
353  // Store the decoded Stream Flags into this_index. This is
354  // needed so that we can print which Check is used in each
355  // Stream.
356  ret = lzma_index_stream_flags(this_index, &footer_flags);
357  if (ret != LZMA_OK)
358  message_bug();
359 
360  // Store also the size of the Stream Padding field. It is
361  // needed to show the offsets of the Streams correctly.
362  ret = lzma_index_stream_padding(this_index, stream_padding);
363  if (ret != LZMA_OK)
364  message_bug();
365 
366  if (combined_index != NULL) {
367  // Append the earlier decoded Indexes
368  // after this_index.
369  ret = lzma_index_cat(
370  this_index, combined_index, NULL);
371  if (ret != LZMA_OK) {
372  message_error("%s: %s", pair->src_name,
373  message_strm(ret));
374  goto error;
375  }
376  }
377 
378  combined_index = this_index;
379  this_index = NULL;
380 
382 
383  } while (pos > 0);
384 
385  lzma_end(&strm);
386 
387  // All OK. Make combined_index available to the caller.
388  xfi->idx = combined_index;
389  return false;
390 
391 error:
392  // Something went wrong, free the allocated memory.
393  lzma_end(&strm);
394  lzma_index_end(combined_index, NULL);
395  lzma_index_end(this_index, NULL);
396  return true;
397 }
@ MODE_LIST
Definition: coder.h:17
static lzma_vli index_size(lzma_vli count, lzma_vli index_list_size)
Calculate the size of the Index field including Index Padding.
Definition: index.h:57
uint64_t memlimit
Definition: container.h:537
#define IO_BUFFER_SIZE
Definition: file_io.h:16
static lzma_stream strm
Definition: full_flush.c:20
uint64_t hardware_memlimit_get(enum operation_mode mode)
Get the current memory usage limit for compression or decompression.
Definition: hardware.c:112
void message_mem_needed(enum message_verbosity v, uint64_t memusage)
Display how much memory was needed and how much the limit was.
Definition: message.c:846
@ V_ERROR
Only error messages.
Definition: message.h:16
unsigned long uint64_t
Definition: sftypes.h:28
#define UINT64_MAX
#define LZMA_STREAM_HEADER_SIZE
Size of Stream Header and Stream Footer.
Definition: stream_flags.h:27
struct stat src_st
Stat of the source file.
Definition: file_io.h:69
Options for encoding/decoding Stream Header and Stream Footer.
Definition: stream_flags.h:33
uint32_t version
Stream Flags format version.
Definition: stream_flags.h:51
lzma_vli backward_size
Backward Size.
Definition: stream_flags.h:69
Passing data to and from liblzma.
Definition: base.h:485
const uint8_t * next_in
Definition: base.h:486
size_t avail_in
Definition: base.h:487
uint64_t stream_padding
Total amount of Stream Padding.
Definition: list.c:23
uint64_t stream_padding
Definition: list.c:107
void error(const char *msg)
Definition: untgz.c:593
uint64_t lzma_vli
Variable-length integer type.
Definition: vli.h:63
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_BUF_ERROR
No progress is possible.
Definition: base.h:191
@ LZMA_MEMLIMIT_ERROR
Definition: base.h:140
@ LZMA_RUN
Continue coding.
Definition: base.h:251
#define LZMA_STREAM_INIT
Initialization for lzma_stream.
Definition: base.h:545

References _, lzma_stream::avail_in, lzma_stream_flags::backward_size, error(), hardware_memlimit_get(), i, xz_file_info::idx, index_size(), IO_BUFFER_SIZE, io_pread(), LZMA_BUF_ERROR, LZMA_DATA_ERROR, LZMA_MEMLIMIT_ERROR, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_RUN, LZMA_STREAM_END, LZMA_STREAM_HEADER_SIZE, LZMA_STREAM_INIT, memlimit, message_bug(), message_error(), message_mem_needed(), message_strm(), MODE_LIST, my_min, lzma_stream::next_in, NULL, pos, file_pair::src_name, file_pair::src_st, xz_file_info::stream_padding, stream_padding, strm, UINT64_MAX, V_ERROR, and lzma_stream_flags::version.

Referenced by list_file().

◆ print_adv_helper()

static void print_adv_helper ( uint64_t  stream_count,
uint64_t  block_count,
uint64_t  compressed_size,
uint64_t  uncompressed_size,
uint32_t  checks,
uint64_t  stream_padding 
)
static

Definition at line 710 of file list.c.

713 {
714  char checks_str[CHECKS_STR_SIZE];
715  get_check_names(checks_str, checks, true);
716 
717  printf(_(" Streams: %s\n"),
718  uint64_to_str(stream_count, 0));
719  printf(_(" Blocks: %s\n"),
720  uint64_to_str(block_count, 0));
721  printf(_(" Compressed size: %s\n"),
723  NICESTR_B, NICESTR_TIB, true, 0));
724  printf(_(" Uncompressed size: %s\n"),
726  NICESTR_B, NICESTR_TIB, true, 0));
727  printf(_(" Ratio: %s\n"),
729  printf(_(" Check: %s\n"), checks_str);
730  printf(_(" Stream padding: %s\n"),
732  NICESTR_B, NICESTR_TIB, true, 0));
733  return;
734 }
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static void get_check_names(char buf[CHECKS_STR_SIZE], uint32_t checks, bool space_after_comma)
Get a comma-separated list of Check names.
Definition: list.c:638
static const char * get_ratio(uint64_t compressed_size, uint64_t uncompressed_size)
Get the compression ratio.
Definition: list.c:611
const char * uint64_to_str(uint64_t value, uint32_t slot)
Convert uint64_t to a string.
Definition: util.c:171
const char * uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min, enum nicestr_unit unit_max, bool always_also_bytes, uint32_t slot)
Convert uint64_t to a nice human readable string.
Definition: util.c:187
@ NICESTR_B
Definition: util.h:65
@ NICESTR_TIB
Definition: util.h:69

References _, checks, CHECKS_STR_SIZE, compressed_size, get_check_names(), get_ratio(), NICESTR_B, NICESTR_TIB, printf(), stream_padding, uint64_to_nicestr(), uint64_to_str(), and uncompressed_size.

Referenced by print_info_adv(), and print_totals_adv().

◆ print_info_adv()

static bool print_info_adv ( xz_file_info xfi,
file_pair pair 
)
static

Definition at line 738 of file list.c.

739 {
740  // Print the overall information.
741  print_adv_helper(lzma_index_stream_count(xfi->idx),
742  lzma_index_block_count(xfi->idx),
743  lzma_index_file_size(xfi->idx),
744  lzma_index_uncompressed_size(xfi->idx),
745  lzma_index_checks(xfi->idx),
746  xfi->stream_padding);
747 
748  // Size of the biggest Check. This is used to calculate the width
749  // of the CheckVal field. The table would get insanely wide if
750  // we always reserved space for 64-byte Check (128 chars as hex).
751  uint32_t check_max = 0;
752 
753  // Print information about the Streams.
754  //
755  // TRANSLATORS: The second line is column headings. All except
756  // Check are right aligned; Check is left aligned. Test with
757  // "xz -lv foo.xz".
758  puts(_(" Streams:\n Stream Blocks"
759  " CompOffset UncompOffset"
760  " CompSize UncompSize Ratio"
761  " Check Padding"));
762 
764  lzma_index_iter_init(&iter, xfi->idx);
765 
766  while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM)) {
767  const char *cols1[4] = {
768  uint64_to_str(iter.stream.number, 0),
769  uint64_to_str(iter.stream.block_count, 1),
770  uint64_to_str(iter.stream.compressed_offset, 2),
771  uint64_to_str(iter.stream.uncompressed_offset, 3),
772  };
773  printf(" %*s %*s %*s %*s ",
774  tuklib_mbstr_fw(cols1[0], 6), cols1[0],
775  tuklib_mbstr_fw(cols1[1], 9), cols1[1],
776  tuklib_mbstr_fw(cols1[2], 15), cols1[2],
777  tuklib_mbstr_fw(cols1[3], 15), cols1[3]);
778 
779  const char *cols2[5] = {
780  uint64_to_str(iter.stream.compressed_size, 0),
781  uint64_to_str(iter.stream.uncompressed_size, 1),
782  get_ratio(iter.stream.compressed_size,
783  iter.stream.uncompressed_size),
784  _(check_names[iter.stream.flags->check]),
785  uint64_to_str(iter.stream.padding, 2),
786  };
787  printf("%*s %*s %*s %-*s %*s\n",
788  tuklib_mbstr_fw(cols2[0], 15), cols2[0],
789  tuklib_mbstr_fw(cols2[1], 15), cols2[1],
790  tuklib_mbstr_fw(cols2[2], 5), cols2[2],
791  tuklib_mbstr_fw(cols2[3], 10), cols2[3],
792  tuklib_mbstr_fw(cols2[4], 7), cols2[4]);
793 
794  // Update the maximum Check size.
795  if (lzma_check_size(iter.stream.flags->check) > check_max)
796  check_max = lzma_check_size(iter.stream.flags->check);
797  }
798 
799  // Cache the verbosity level to a local variable.
800  const bool detailed = message_verbosity_get() >= V_DEBUG;
801 
802  // Information collected from Block Headers
803  block_header_info bhi;
804 
805  // Print information about the Blocks but only if there is
806  // at least one Block.
807  if (lzma_index_block_count(xfi->idx) > 0) {
808  // Calculate the width of the CheckVal field.
809  const int checkval_width = my_max(8, 2 * check_max);
810 
811  // TRANSLATORS: The second line is column headings. All
812  // except Check are right aligned; Check is left aligned.
813  printf(_(" Blocks:\n Stream Block"
814  " CompOffset UncompOffset"
815  " TotalSize UncompSize Ratio Check"));
816 
817  if (detailed) {
818  // TRANSLATORS: These are additional column headings
819  // for the most verbose listing mode. CheckVal
820  // (Check value), Flags, and Filters are left aligned.
821  // Header (Block Header Size), CompSize, and MemUsage
822  // are right aligned. %*s is replaced with 0-120
823  // spaces to make the CheckVal column wide enough.
824  // Test with "xz -lvv foo.xz".
825  printf(_(" CheckVal %*s Header Flags "
826  "CompSize MemUsage Filters"),
827  checkval_width - 8, "");
828  }
829 
830  putchar('\n');
831 
832  lzma_index_iter_init(&iter, xfi->idx);
833 
834  // Iterate over the Blocks.
835  while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
836  if (detailed && parse_details(pair, &iter, &bhi, xfi))
837  return true;
838 
839  const char *cols1[4] = {
840  uint64_to_str(iter.stream.number, 0),
842  iter.block.number_in_stream, 1),
844  iter.block.compressed_file_offset, 2),
846  iter.block.uncompressed_file_offset, 3)
847  };
848  printf(" %*s %*s %*s %*s ",
849  tuklib_mbstr_fw(cols1[0], 6), cols1[0],
850  tuklib_mbstr_fw(cols1[1], 9), cols1[1],
851  tuklib_mbstr_fw(cols1[2], 15), cols1[2],
852  tuklib_mbstr_fw(cols1[3], 15), cols1[3]);
853 
854  const char *cols2[4] = {
855  uint64_to_str(iter.block.total_size, 0),
856  uint64_to_str(iter.block.uncompressed_size,
857  1),
858  get_ratio(iter.block.total_size,
859  iter.block.uncompressed_size),
860  _(check_names[iter.stream.flags->check])
861  };
862  printf("%*s %*s %*s %-*s",
863  tuklib_mbstr_fw(cols2[0], 15), cols2[0],
864  tuklib_mbstr_fw(cols2[1], 15), cols2[1],
865  tuklib_mbstr_fw(cols2[2], 5), cols2[2],
866  tuklib_mbstr_fw(cols2[3], detailed ? 11 : 1),
867  cols2[3]);
868 
869  if (detailed) {
871  = iter.block.unpadded_size
872  - bhi.header_size
873  - lzma_check_size(
874  iter.stream.flags->check);
875 
876  const char *cols3[6] = {
877  check_value,
878  uint64_to_str(bhi.header_size, 0),
879  bhi.flags,
883  2),
884  bhi.filter_chain
885  };
886  // Show MiB for memory usage, because it
887  // is the only size which is not in bytes.
888  printf("%-*s %*s %-5s %*s %*s MiB %s",
889  checkval_width, cols3[0],
890  tuklib_mbstr_fw(cols3[1], 6), cols3[1],
891  cols3[2],
892  tuklib_mbstr_fw(cols3[3], 15),
893  cols3[3],
894  tuklib_mbstr_fw(cols3[4], 7), cols3[4],
895  cols3[5]);
896  }
897 
898  putchar('\n');
899  }
900  }
901 
902  if (detailed) {
903  printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
904  round_up_to_mib(xfi->memusage_max), 0));
905  printf(_(" Sizes in headers: %s\n"),
906  xfi->all_have_sizes ? _("Yes") : _("No"));
907  printf(_(" Minimum XZ Utils version: %s\n"),
908  xz_ver_to_str(xfi->min_version));
909  }
910 
911  return false;
912 }
@ LZMA_INDEX_ITER_BLOCK
Get the next Block.
Definition: index.h:249
@ LZMA_INDEX_ITER_STREAM
Get the next Stream.
Definition: index.h:238
@ V_DEBUG
Very verbose.
Definition: message.h:19
Information about a .xz Block.
Definition: list.c:41
Iterator to get information about Blocks and Streams.
Definition: index.h:43
static const char * xz_ver_to_str(uint32_t ver)
Convert XZ Utils version number to a string.
Definition: list.c:117
static void print_adv_helper(uint64_t stream_count, uint64_t block_count, uint64_t compressed_size, uint64_t uncompressed_size, uint32_t checks, uint64_t stream_padding)
Definition: list.c:710
static bool parse_details(file_pair *pair, const lzma_index_iter *iter, block_header_info *bhi, xz_file_info *xfi)
Parse detailed information about a Block.
Definition: list.c:594
uint64_t round_up_to_mib(uint64_t n)
Round an integer up to the next full MiB and convert to MiB.
Definition: util.c:139
#define my_max(x, y)
Definition: sysdefs.h:186
#define tuklib_mbstr_fw
Definition: tuklib_mbstr.h:45

References _, xz_file_info::all_have_sizes, check_names, check_value, compressed_size, block_header_info::filter_chain, block_header_info::flags, get_ratio(), block_header_info::header_size, xz_file_info::idx, LZMA_INDEX_ITER_BLOCK, LZMA_INDEX_ITER_STREAM, block_header_info::memusage, xz_file_info::memusage_max, message_verbosity_get(), xz_file_info::min_version, my_max, parse_details(), print_adv_helper(), printf(), round_up_to_mib(), xz_file_info::stream_padding, tuklib_mbstr_fw, uint64_to_str(), V_DEBUG, and xz_ver_to_str().

Referenced by list_file().

◆ print_info_basic()

static bool print_info_basic ( const xz_file_info xfi,
file_pair pair 
)
static

Definition at line 668 of file list.c.

669 {
670  static bool headings_displayed = false;
671  if (!headings_displayed) {
672  headings_displayed = true;
673  // TRANSLATORS: These are column headings. From Strms (Streams)
674  // to Ratio, the columns are right aligned. Check and Filename
675  // are left aligned. If you need longer words, it's OK to
676  // use two lines here. Test with "xz -l foo.xz".
677  puts(_("Strms Blocks Compressed Uncompressed Ratio "
678  "Check Filename"));
679  }
680 
681  char checks[CHECKS_STR_SIZE];
682  get_check_names(checks, lzma_index_checks(xfi->idx), false);
683 
684  const char *cols[7] = {
685  uint64_to_str(lzma_index_stream_count(xfi->idx), 0),
686  uint64_to_str(lzma_index_block_count(xfi->idx), 1),
687  uint64_to_nicestr(lzma_index_file_size(xfi->idx),
688  NICESTR_B, NICESTR_TIB, false, 2),
689  uint64_to_nicestr(lzma_index_uncompressed_size(xfi->idx),
690  NICESTR_B, NICESTR_TIB, false, 3),
691  get_ratio(lzma_index_file_size(xfi->idx),
692  lzma_index_uncompressed_size(xfi->idx)),
693  checks,
694  pair->src_name,
695  };
696  printf("%*s %*s %*s %*s %*s %-*s %s\n",
697  tuklib_mbstr_fw(cols[0], 5), cols[0],
698  tuklib_mbstr_fw(cols[1], 7), cols[1],
699  tuklib_mbstr_fw(cols[2], 11), cols[2],
700  tuklib_mbstr_fw(cols[3], 11), cols[3],
701  tuklib_mbstr_fw(cols[4], 5), cols[4],
702  tuklib_mbstr_fw(cols[5], 7), cols[5],
703  cols[6]);
704 
705  return false;
706 }

References _, checks, CHECKS_STR_SIZE, get_check_names(), get_ratio(), xz_file_info::idx, NICESTR_B, NICESTR_TIB, printf(), file_pair::src_name, tuklib_mbstr_fw, uint64_to_nicestr(), and uint64_to_str().

Referenced by list_file().

◆ print_info_robot()

static bool print_info_robot ( xz_file_info xfi,
file_pair pair 
)
static

Definition at line 916 of file list.c.

917 {
918  char checks[CHECKS_STR_SIZE];
919  get_check_names(checks, lzma_index_checks(xfi->idx), false);
920 
921  printf("name\t%s\n", pair->src_name);
922 
923  printf("file\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
924  "\t%s\t%s\t%" PRIu64 "\n",
925  lzma_index_stream_count(xfi->idx),
926  lzma_index_block_count(xfi->idx),
927  lzma_index_file_size(xfi->idx),
928  lzma_index_uncompressed_size(xfi->idx),
929  get_ratio(lzma_index_file_size(xfi->idx),
930  lzma_index_uncompressed_size(xfi->idx)),
931  checks,
932  xfi->stream_padding);
933 
934  if (message_verbosity_get() >= V_VERBOSE) {
936  lzma_index_iter_init(&iter, xfi->idx);
937 
938  while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM))
939  printf("stream\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
940  "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
941  "\t%s\t%s\t%" PRIu64 "\n",
942  iter.stream.number,
943  iter.stream.block_count,
944  iter.stream.compressed_offset,
945  iter.stream.uncompressed_offset,
946  iter.stream.compressed_size,
947  iter.stream.uncompressed_size,
948  get_ratio(iter.stream.compressed_size,
949  iter.stream.uncompressed_size),
950  check_names[iter.stream.flags->check],
951  iter.stream.padding);
952 
953  lzma_index_iter_rewind(&iter);
954  block_header_info bhi;
955 
956  while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
958  && parse_details(
959  pair, &iter, &bhi, xfi))
960  return true;
961 
962  printf("block\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
963  "\t%" PRIu64 "\t%" PRIu64
964  "\t%" PRIu64 "\t%" PRIu64 "\t%s\t%s",
965  iter.stream.number,
966  iter.block.number_in_stream,
967  iter.block.number_in_file,
968  iter.block.compressed_file_offset,
969  iter.block.uncompressed_file_offset,
970  iter.block.total_size,
971  iter.block.uncompressed_size,
972  get_ratio(iter.block.total_size,
973  iter.block.uncompressed_size),
974  check_names[iter.stream.flags->check]);
975 
977  printf("\t%s\t%" PRIu32 "\t%s\t%" PRIu64
978  "\t%" PRIu64 "\t%s",
979  check_value,
980  bhi.header_size,
981  bhi.flags,
982  bhi.compressed_size,
983  bhi.memusage,
984  bhi.filter_chain);
985 
986  putchar('\n');
987  }
988  }
989 
991  printf("summary\t%" PRIu64 "\t%s\t%" PRIu32 "\n",
992  xfi->memusage_max,
993  xfi->all_have_sizes ? "yes" : "no",
994  xfi->min_version);
995 
996  return false;
997 }
#define PRIu32
Definition: macros.h:20
#define PRIu64
Definition: macros.h:18
@ V_VERBOSE
Errors, warnings, and verbose statistics.
Definition: message.h:18

References xz_file_info::all_have_sizes, check_names, check_value, checks, CHECKS_STR_SIZE, block_header_info::compressed_size, block_header_info::filter_chain, block_header_info::flags, get_check_names(), get_ratio(), block_header_info::header_size, xz_file_info::idx, LZMA_INDEX_ITER_BLOCK, LZMA_INDEX_ITER_STREAM, block_header_info::memusage, xz_file_info::memusage_max, message_verbosity_get(), xz_file_info::min_version, parse_details(), printf(), PRIu32, PRIu64, file_pair::src_name, xz_file_info::stream_padding, V_DEBUG, and V_VERBOSE.

Referenced by list_file().

◆ print_totals_adv()

static void print_totals_adv ( void  )
static

Definition at line 1067 of file list.c.

1068 {
1069  putchar('\n');
1070  puts(_("Totals:"));
1071  printf(_(" Number of files: %s\n"),
1072  uint64_to_str(totals.files, 0));
1073  print_adv_helper(totals.streams, totals.blocks,
1074  totals.compressed_size, totals.uncompressed_size,
1075  totals.checks, totals.stream_padding);
1076 
1077  if (message_verbosity_get() >= V_DEBUG) {
1078  printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
1079  round_up_to_mib(totals.memusage_max), 0));
1080  printf(_(" Sizes in headers: %s\n"),
1081  totals.all_have_sizes ? _("Yes") : _("No"));
1082  printf(_(" Minimum XZ Utils version: %s\n"),
1083  xz_ver_to_str(totals.min_version));
1084  }
1085 
1086  return;
1087 }

References _, message_verbosity_get(), print_adv_helper(), printf(), round_up_to_mib(), totals, uint64_to_str(), V_DEBUG, and xz_ver_to_str().

Referenced by list_totals().

◆ print_totals_basic()

static void print_totals_basic ( void  )
static

Definition at line 1025 of file list.c.

1026 {
1027  // Print a separator line.
1028  char line[80];
1029  memset(line, '-', sizeof(line));
1030  line[sizeof(line) - 1] = '\0';
1031  puts(line);
1032 
1033  // Get the check names.
1034  char checks[CHECKS_STR_SIZE];
1035  get_check_names(checks, totals.checks, false);
1036 
1037  // Print the totals except the file count, which needs
1038  // special handling.
1039  printf("%5s %7s %11s %11s %5s %-7s ",
1040  uint64_to_str(totals.streams, 0),
1041  uint64_to_str(totals.blocks, 1),
1042  uint64_to_nicestr(totals.compressed_size,
1043  NICESTR_B, NICESTR_TIB, false, 2),
1044  uint64_to_nicestr(totals.uncompressed_size,
1045  NICESTR_B, NICESTR_TIB, false, 3),
1046  get_ratio(totals.compressed_size,
1047  totals.uncompressed_size),
1048  checks);
1049 
1050  // Since we print totals only when there are at least two files,
1051  // the English message will always use "%s files". But some other
1052  // languages need different forms for different plurals so we
1053  // have to translate this with ngettext().
1054  //
1055  // TRANSLATORS: %s is an integer. Only the plural form of this
1056  // message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz".
1057  printf(ngettext("%s file\n", "%s files\n",
1058  totals.files <= ULONG_MAX ? totals.files
1059  : (totals.files % 1000000) + 1000000),
1060  uint64_to_str(totals.files, 0));
1061 
1062  return;
1063 }
return memset(p, 0, total)
line
Definition: setup.py:34
#define ngettext(msgid1, msgid2, n)

References checks, CHECKS_STR_SIZE, get_check_names(), get_ratio(), setup::line, memset(), ngettext, NICESTR_B, NICESTR_TIB, printf(), totals, uint64_to_nicestr(), and uint64_to_str().

Referenced by list_totals().

◆ print_totals_robot()

static void print_totals_robot ( void  )
static

Definition at line 1091 of file list.c.

1092 {
1093  char checks[CHECKS_STR_SIZE];
1094  get_check_names(checks, totals.checks, false);
1095 
1096  printf("totals\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
1097  "\t%s\t%s\t%" PRIu64 "\t%" PRIu64,
1098  totals.streams,
1099  totals.blocks,
1100  totals.compressed_size,
1101  totals.uncompressed_size,
1102  get_ratio(totals.compressed_size,
1103  totals.uncompressed_size),
1104  checks,
1105  totals.stream_padding,
1106  totals.files);
1107 
1108  if (message_verbosity_get() >= V_DEBUG)
1109  printf("\t%" PRIu64 "\t%s\t%" PRIu32,
1110  totals.memusage_max,
1111  totals.all_have_sizes ? "yes" : "no",
1112  totals.min_version);
1113 
1114  putchar('\n');
1115 
1116  return;
1117 }

References checks, CHECKS_STR_SIZE, get_check_names(), get_ratio(), message_verbosity_get(), printf(), PRIu32, PRIu64, totals, and V_DEBUG.

Referenced by list_totals().

◆ update_totals()

static void update_totals ( const xz_file_info xfi)
static

Definition at line 1001 of file list.c.

1002 {
1003  // TODO: Integer overflow checks
1004  ++totals.files;
1005  totals.streams += lzma_index_stream_count(xfi->idx);
1006  totals.blocks += lzma_index_block_count(xfi->idx);
1007  totals.compressed_size += lzma_index_file_size(xfi->idx);
1008  totals.uncompressed_size += lzma_index_uncompressed_size(xfi->idx);
1009  totals.stream_padding += xfi->stream_padding;
1010  totals.checks |= lzma_index_checks(xfi->idx);
1011 
1012  if (totals.memusage_max < xfi->memusage_max)
1013  totals.memusage_max = xfi->memusage_max;
1014 
1015  if (totals.min_version < xfi->min_version)
1016  totals.min_version = xfi->min_version;
1017 
1018  totals.all_have_sizes &= xfi->all_have_sizes;
1019 
1020  return;
1021 }

References xz_file_info::all_have_sizes, xz_file_info::idx, xz_file_info::memusage_max, xz_file_info::min_version, xz_file_info::stream_padding, and totals.

Referenced by list_file().

◆ xz_ver_to_str()

static const char* xz_ver_to_str ( uint32_t  ver)
static

Convert XZ Utils version number to a string.

Definition at line 117 of file list.c.

118 {
119  static char buf[32];
120 
121  unsigned int major = ver / 10000000U;
122  ver -= major * 10000000U;
123 
124  unsigned int minor = ver / 10000U;
125  ver -= minor * 10000U;
126 
127  unsigned int patch = ver / 10U;
128  ver -= patch * 10U;
129 
130  const char *stability = ver == 0 ? "alpha" : ver == 1 ? "beta" : "";
131 
132  snprintf(buf, sizeof(buf), "%u.%u.%u%s",
133  major, minor, patch, stability);
134  return buf;
135 }
#define minor(dev)
Definition: fsmagic.c:57
#define major(dev)
Definition: fsmagic.c:56

References major, minor, and snprintf.

Referenced by print_info_adv(), and print_totals_adv().

Variable Documentation

◆ all_have_sizes

bool all_have_sizes

Definition at line 111 of file list.c.

◆ blocks

◆ check_names

const char check_names[LZMA_CHECK_ID_MAX+1][12]
static
Initial value:
= {
N_("None"),
"CRC32",
N_("Unknown-2"),
N_("Unknown-3"),
"CRC64",
N_("Unknown-5"),
N_("Unknown-6"),
N_("Unknown-7"),
N_("Unknown-8"),
N_("Unknown-9"),
"SHA-256",
N_("Unknown-11"),
N_("Unknown-12"),
N_("Unknown-13"),
N_("Unknown-14"),
N_("Unknown-15"),
}
#define N_(String)
Definition: opintl.h:54

Check ID to string mapping.

Definition at line 61 of file list.c.

Referenced by get_check_names(), print_info_adv(), and print_info_robot().

◆ check_value

char check_value[2 *LZMA_CHECK_SIZE_MAX+1]
static

Value of the Check field as hexadecimal string. This is set by parse_check_value().

Definition at line 95 of file list.c.

Referenced by parse_check_value(), print_info_adv(), and print_info_robot().

◆ checks

◆ compressed_size

◆ files

uint64_t files

Definition at line 102 of file list.c.

◆ memusage_max

uint64_t memusage_max

Definition at line 108 of file list.c.

◆ min_version

uint32_t min_version

Definition at line 110 of file list.c.

◆ stream_padding

uint64_t stream_padding

Definition at line 107 of file list.c.

Referenced by index_file_size(), parse_indexes(), and print_adv_helper().

◆ streams

uint64_t streams

Definition at line 103 of file list.c.

Referenced by bin_pe_dotnet_init_metadata(), LZMA_API(), pdb7_extract_streams(), and rz_test_main().

◆ 

struct { ... } totals

Totals that are displayed if there was more than one file. The "files" counter is also used in print_info_adv() to show the file number.

Referenced by list_totals(), print_totals_adv(), print_totals_basic(), print_totals_robot(), and update_totals().

◆ uncompressed_size