feat: handle Ctrl+C gracefully, cleaning up partial output
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include "fpk.h"
|
#include "fpk.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -100,6 +101,13 @@ static void format_duration(double secs, char *buf, size_t bufsize)
|
|||||||
static unsigned char flags;
|
static unsigned char flags;
|
||||||
static uint64_t entry_count;
|
static uint64_t entry_count;
|
||||||
static uint64_t total_bytes;
|
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[] = {
|
static struct option long_opts[] = {
|
||||||
{"output", required_argument, NULL, 'o'},
|
{"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;
|
size_t size;
|
||||||
char *norm;
|
char *norm;
|
||||||
|
|
||||||
|
if (interrupted)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (*rel_path == '/')
|
while (*rel_path == '/')
|
||||||
rel_path++;
|
rel_path++;
|
||||||
|
|
||||||
@@ -439,8 +450,16 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, handle_sigint);
|
||||||
|
|
||||||
if (!add_dir(w, input_dir, base_len)) {
|
if (!add_dir(w, input_dir, base_len)) {
|
||||||
fpk_writer_close(w);
|
fpk_writer_close(w);
|
||||||
|
if (interrupted) {
|
||||||
|
remove(output);
|
||||||
|
fprintf(stderr, "\nfpack: interrupted, removed incomplete archive: %s\n", output);
|
||||||
|
free(output);
|
||||||
|
return 130;
|
||||||
|
}
|
||||||
free(output);
|
free(output);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -5,6 +5,7 @@
|
|||||||
#include "fpk.h"
|
#include "fpk.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -102,6 +103,13 @@ static void format_duration(double secs, char *buf, size_t bufsize)
|
|||||||
#define FUNPACK_VERBOSE (1u << 3)
|
#define FUNPACK_VERBOSE (1u << 3)
|
||||||
|
|
||||||
static unsigned char flags;
|
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[] = {
|
static struct option long_opts[] = {
|
||||||
{"dir", required_argument, NULL, 'd'},
|
{"dir", required_argument, NULL, 'd'},
|
||||||
@@ -340,10 +348,17 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, handle_sigint);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
const fpk_entry_t *entry = fpk_entry_at(pak, i);
|
const fpk_entry_t *entry = fpk_entry_at(pak, i);
|
||||||
size_t size;
|
size_t size;
|
||||||
void *data = fpk_read(pak, entry, &size);
|
void *data;
|
||||||
|
|
||||||
|
if (interrupted)
|
||||||
|
break;
|
||||||
|
|
||||||
|
data = fpk_read(pak, entry, &size);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
fprintf(stderr, "funpack: cannot read: %s\n", entry->path);
|
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)
|
if ((flags & FUNPACK_PROGRESS) && count > 0)
|
||||||
printf("\n");
|
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)) {
|
if (!(flags & FUNPACK_QUIET)) {
|
||||||
char dur[64];
|
char dur[64];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user