diff --git a/src/main.c b/src/main.c index ef84fa5..6a5b623 100644 --- a/src/main.c +++ b/src/main.c @@ -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 ────────────────────────────────────── static char *tar_directory(const char *dir_path) { 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 ───────────────────────────────────────────── static int cmd_decompress(const char *archive_path, const char *output_path, 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_start(&total_timer); - // Read archive VkzArchive *archive = vkz_read(archive_path); - if (!archive) + if (!archive) { return 1; - + } vkz_print_info(archive); // Generate output path if not provided