From 8233150b4ed2c4a6e1639e7d5e578f4b6b2a363a Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sun, 27 Sep 2026 23:13:06 +0200 Subject: zip.c: Add top-level directory It is desirable to keep the contents of the generated file below a directory, ideally named after the ZIP file itself, so that extraction tools can extract the files to a subdirectory, rather than spilling its contents to the working directory. --- zip.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/zip.c b/zip.c index 668030c..c6cde50 100644 --- a/zip.c +++ b/zip.c @@ -152,29 +152,46 @@ static int read_file(void *const buf, const size_t n, bool *const done, static int setup_file(struct zip *const z, const char *const fpath, const time_t t) { + int ret = -1, fd = -1; struct stat sb; + struct dynstr d; + char *bndup = NULL; ZIPentry *entry = NULL; - const int fd = open(fpath, O_RDONLY | O_NONBLOCK); - /* zs_entrybegin is not const-correct. */ - char *path = (char *)fpath + strlen(z->basedir); + const char *path = fpath + strlen(z->basedir), *bn; + + dynstr_init(&d); - if (fd < 0) + if (!(bndup = strdup(z->basedir))) + { + fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno)); + goto end; + } + else if (!(bn = basename(bndup))) + { + fprintf(stderr, "%s: basename(3) failed\n", __func__); + goto end; + } + else if (dynstr_append(&d, "%s/%s", bn, path)) + { + fprintf(stderr, "%s: dynstr_append failed\n", __func__); + goto end; + } + else if ((fd = open(fpath, O_RDONLY | O_NONBLOCK)) < 0) { fprintf(stderr, "%s: open(2) %s: %s\n", __func__, fpath, strerror(errno)); - goto failure; + goto end; } else if (fstat(fd, &sb)) { fprintf(stderr, "%s: fstat(2) %s: %s\n", __func__, fpath, strerror(errno)); - goto failure; + goto end; } - else if (!(entry = zs_entrybegin(z->stream, path, t, ZS_DEFLATE, - NULL))) + else if (!(entry = zs_entrybegin(z->stream, d.str, t, ZS_DEFLATE, NULL))) { fprintf(stderr, "%s: zs_entrybegin failed\n", __func__); - goto failure; + goto end; } z->fd = fd; @@ -182,15 +199,16 @@ static int setup_file(struct zip *const z, const char *const fpath, z->entry = entry; z->filesz = sb.st_size; z->next = read_file; - return 0; + ret = 0; +end: -failure: - - if (fd && close(fd)) + if (ret && fd >= 0 && close(fd)) fprintf(stderr, "%s: close(2) %s: %s\n", __func__, fpath, strerror(errno)); - return -1; + dynstr_free(&d); + free(bndup); + return ret; } static int setup(const char *const fpath, const struct stat *sb, -- cgit v1.2.3