From cea82dfe50503a0095b333d9c0ef8fc42856f14c Mon Sep 17 00:00:00 2001 From: anth64 Date: Tue, 15 Sep 2026 14:06:23 +0200 Subject: [PATCH] feat: handle Ctrl+C gracefully, cleaning up partial output --- tools/fpack.c | 19 +++++++++++++++++++ tools/funpack.c | 24 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tools/fpack.c b/tools/fpack.c index b8dfc77..de418d6 100644 --- a/tools/fpack.c +++ b/tools/fpack.c @@ -6,6 +6,7 @@ #include "fpk.h" #include #include +#include #include #include #include @@ -100,6 +101,13 @@ static void format_duration(double secs, char *buf, size_t bufsize) static unsigned char flags; static uint64_t entry_count; static uint64_t total_bytes; +static volatile sig_atomic_t interrupted; + +static void handle_sigint(int sig) +{ + (void)sig; + interrupted = 1; +} static struct option long_opts[] = { {"output", required_argument, NULL, 'o'}, @@ -229,6 +237,9 @@ static int add_file(struct fpk_writer *w, const char *path, size_t base_len) size_t size; char *norm; + if (interrupted) + return 0; + while (*rel_path == '/') rel_path++; @@ -439,8 +450,16 @@ int main(int argc, char **argv) return 1; } + signal(SIGINT, handle_sigint); + if (!add_dir(w, input_dir, base_len)) { fpk_writer_close(w); + if (interrupted) { + remove(output); + fprintf(stderr, "\nfpack: interrupted, removed incomplete archive: %s\n", output); + free(output); + return 130; + } free(output); return 1; } diff --git a/tools/funpack.c b/tools/funpack.c index 0ea6b75..63b7a13 100644 --- a/tools/funpack.c +++ b/tools/funpack.c @@ -5,6 +5,7 @@ #include "fpk.h" #include #include +#include #include #include #include @@ -102,6 +103,13 @@ static void format_duration(double secs, char *buf, size_t bufsize) #define FUNPACK_VERBOSE (1u << 3) static unsigned char flags; +static volatile sig_atomic_t interrupted; + +static void handle_sigint(int sig) +{ + (void)sig; + interrupted = 1; +} static struct option long_opts[] = { {"dir", required_argument, NULL, 'd'}, @@ -340,10 +348,17 @@ int main(int argc, char **argv) return 1; } + signal(SIGINT, handle_sigint); + for (i = 0; i < count; i++) { const fpk_entry_t *entry = fpk_entry_at(pak, i); size_t size; - void *data = fpk_read(pak, entry, &size); + void *data; + + if (interrupted) + break; + + data = fpk_read(pak, entry, &size); if (!data) { fprintf(stderr, "funpack: cannot read: %s\n", entry->path); @@ -377,6 +392,13 @@ int main(int argc, char **argv) if ((flags & FUNPACK_PROGRESS) && count > 0) printf("\n"); + if (interrupted) { + fprintf(stderr, "funpack: interrupted, %lu of %lu entries extracted\n", + (unsigned long)i, (unsigned long)count); + free(out_dir); + return 130; + } + if (!(flags & FUNPACK_QUIET)) { char dur[64];