feat: Add intelligent extraction support for regular .zip and .rar archives using system tools

This commit is contained in:
2026-04-20 23:29:47 -03:00
parent 65b41d4d0b
commit e3ec8d2128
+72 -3
View File
@@ -129,6 +129,68 @@ static void strip_trailing_slash(char *path) {
} }
} }
// ── Check file extension ───────────────────────────────────────────
static bool ends_with(const char *str, const char *suffix) {
if (!str || !suffix)
return false;
size_t lenstr = strlen(str);
size_t lensuffix = strlen(suffix);
if (lensuffix > lenstr)
return false;
return strcasecmp(str + lenstr - lensuffix, suffix) == 0;
}
// ── Extract external archives via system ───────────────────────────
static int extract_external_archive(const char *input_path,
const char *output_dir, const char *type) {
char cmd[VKZ_MAX_FILENAME * 3];
// Create output dir if specified
if (output_dir) {
#ifdef _WIN32
snprintf(cmd, sizeof(cmd), "if not exist \"%s\" mkdir \"%s\"", output_dir,
output_dir);
#else
snprintf(cmd, sizeof(cmd), "mkdir -p '%s'", output_dir);
#endif
system(cmd);
}
const char *out_target = output_dir ? output_dir : ".";
if (strcmp(type, "zip") == 0) {
LOG_INFO("Extracting ZIP archive using system tools...");
#ifdef _WIN32
snprintf(cmd, sizeof(cmd), "tar -xf \"%s\" -C \"%s\"", input_path,
out_target);
#else
snprintf(cmd, sizeof(cmd), "unzip -q -o '%s' -d '%s'", input_path,
out_target);
#endif
} else if (strcmp(type, "rar") == 0) {
LOG_INFO("Extracting RAR archive using system tools...");
#ifdef _WIN32
snprintf(cmd, sizeof(cmd), "unrar x -y \"%s\" \"%s\\\"", input_path,
out_target);
#else
snprintf(cmd, sizeof(cmd), "unrar x -y '%s' '%s/'", input_path, out_target);
#endif
} else {
return -1;
}
Timer timer;
timer_start(&timer);
if (system(cmd) == 0) {
double time = timer_stop(&timer);
LOG_OK("Extraction complete! (%.3f seconds)", time);
return 0;
} else {
LOG_ERR("Extraction failed. Do you have %s installed?", type);
return 1;
}
}
// ── Create tar from directory ────────────────────────────────────── // ── Create tar from directory ──────────────────────────────────────
static char *tar_directory(const char *dir_path) { static char *tar_directory(const char *dir_path) {
static char tar_path[VKZ_MAX_FILENAME]; static char tar_path[VKZ_MAX_FILENAME];
@@ -416,14 +478,21 @@ static int cmd_compress(const char *input_path, const char *output_path,
// ── Decompress command ───────────────────────────────────────────── // ── Decompress command ─────────────────────────────────────────────
static int cmd_decompress(const char *archive_path, const char *output_path, static int cmd_decompress(const char *archive_path, const char *output_path,
bool cpu_only) { bool cpu_only) {
// Check for standard external archives (zip, rar)
if (ends_with(archive_path, ".zip")) {
return extract_external_archive(archive_path, output_path, "zip");
} else if (ends_with(archive_path, ".rar")) {
return extract_external_archive(archive_path, output_path, "rar");
}
// Native VKZ decompression
Timer total_timer; Timer total_timer;
timer_start(&total_timer); timer_start(&total_timer);
// Read archive
VkzArchive *archive = vkz_read(archive_path); VkzArchive *archive = vkz_read(archive_path);
if (!archive) if (!archive) {
return 1; return 1;
}
vkz_print_info(archive); vkz_print_info(archive);
// Generate output path if not provided // Generate output path if not provided