aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/xz/list.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/xz/list.c b/src/xz/list.c
index 98307eb2..e71fbe20 100644
--- a/src/xz/list.c
+++ b/src/xz/list.c
@@ -29,9 +29,12 @@ typedef struct {
/// Uncompressed Size fields
bool all_have_sizes;
+ /// Oldest XZ Utils version that will decompress the file
+ uint32_t min_version;
+
} xz_file_info;
-#define XZ_FILE_INFO_INIT { NULL, 0, 0, true }
+#define XZ_FILE_INFO_INIT { NULL, 0, 0, true, 50000002 }
/// Information about a .xz Block
@@ -104,8 +107,32 @@ static struct {
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, true };
+} totals = { 0, 0, 0, 0, 0, 0, 0, 0, 0, true };
+
+
+/// Convert XZ Utils version number to a string.
+static const char *
+xz_ver_to_str(uint32_t ver)
+{
+ static char buf[32];
+
+ unsigned int major = ver / 10000000U;
+ ver -= major * 10000000U;
+
+ unsigned int minor = ver / 10000U;
+ ver -= minor * 10000U;
+
+ unsigned int patch = ver / 10U;
+ ver -= patch * 10U;
+
+ const char *stability = ver == 0 ? "alpha" : ver == 1 ? "beta" : "";
+
+ snprintf(buf, sizeof(buf), "%u.%u.%u%s",
+ major, minor, patch, stability);
+ return buf;
+}
/// \brief Parse the Index(es) from the given .xz file
@@ -452,6 +479,21 @@ parse_block_header(file_pair *pair, const lzma_index_iter *iter,
if (xfi->memusage_max < bhi->memusage)
xfi->memusage_max = bhi->memusage;
+ // Determine the minimum XZ Utils version that supports this Block.
+ //
+ // Currently the only thing that 5.0.0 doesn't support is empty
+ // LZMA2 Block. This bug was fixed in 5.0.3.
+ {
+ size_t i = 0;
+ while (filters[i + 1].id != LZMA_VLI_UNKNOWN)
+ ++i;
+
+ if (filters[i].id == LZMA_FILTER_LZMA2
+ && iter->block.uncompressed_size == 0
+ && xfi->min_version < 50000032U)
+ xfi->min_version = 50000032U;
+ }
+
// Convert the filter chain to human readable form.
message_filters_to_str(bhi->filter_chain, filters, false);
@@ -830,6 +872,8 @@ print_info_adv(xz_file_info *xfi, file_pair *pair)
round_up_to_mib(xfi->memusage_max), 0));
printf(_(" Sizes in headers: %s\n"),
xfi->all_have_sizes ? _("Yes") : _("No"));
+ printf(_(" Minimum XZ Utils version: %s\n"),
+ xz_ver_to_str(xfi->min_version));
}
return false;
@@ -912,9 +956,10 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
}
if (message_verbosity_get() >= V_DEBUG)
- printf("summary\t%" PRIu64 "\t%s\n",
+ printf("summary\t%" PRIu64 "\t%s\t%" PRIu32 "\n",
xfi->memusage_max,
- xfi->all_have_sizes ? "yes" : "no");
+ xfi->all_have_sizes ? "yes" : "no",
+ xfi->min_version);
return false;
}
@@ -935,6 +980,9 @@ update_totals(const xz_file_info *xfi)
if (totals.memusage_max < xfi->memusage_max)
totals.memusage_max = xfi->memusage_max;
+ if (totals.min_version < xfi->min_version)
+ totals.min_version = xfi->min_version;
+
totals.all_have_sizes &= xfi->all_have_sizes;
return;
@@ -999,6 +1047,8 @@ print_totals_adv(void)
round_up_to_mib(totals.memusage_max), 0));
printf(_(" Sizes in headers: %s\n"),
totals.all_have_sizes ? _("Yes") : _("No"));
+ printf(_(" Minimum XZ Utils version: %s\n"),
+ xz_ver_to_str(totals.min_version));
}
return;
@@ -1024,9 +1074,10 @@ print_totals_robot(void)
totals.files);
if (message_verbosity_get() >= V_DEBUG)
- printf("\t%" PRIu64 "\t%s",
+ printf("\t%" PRIu64 "\t%s\t%" PRIu32,
totals.memusage_max,
- totals.all_have_sizes ? "yes" : "no");
+ totals.all_have_sizes ? "yes" : "no",
+ totals.min_version);
putchar('\n');