sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit 560e2c4c2b2d583d9e6147bc1aed007613daa2de
parent 2116ce06806406b1aac5be1a021be1b14c93329e
Author: sin <sin@2f30.org>
Date:   Mon Apr 20 16:31:51 +0100

Fix tar(1) handling of archives with improper internal order

Not all archives are packed in such way to be generated without
having to recursively generate the output path.

For now, reuse the function from mkdir.c and later move it to
libutil.

Diffstat:
tar.c | 30+++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/tar.c b/tar.c @@ -4,6 +4,7 @@ #include <errno.h> #include <grp.h> +#include <libgen.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> @@ -173,19 +174,46 @@ archive(const char *path) } static int +mkdirp(char *path) +{ + char *p; + + for (p = path; *p; p++) { + if (*p != '/') + continue; + *p = '\0'; + if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) { + weprintf("mkdir %s:", path); + *p = '/'; + return -1; + } + *p = '/'; + } + if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST) { + weprintf("mkdir %s:", path); + return -1; + } + return 0; +} + +static int unarchive(char *fname, ssize_t l, char b[BLKSIZ]) { FILE *f = NULL; struct timeval times[2]; struct header *h = (void *)b; long mode, major, minor, type, mtime, uid, gid; - char lname[101], *p; + char lname[101], *tmp, *p; if (!mflag && ((mtime = strtoul(h->mtime, &p, 8)) < 0 || *p != '\0')) eprintf("strtoul %s: invalid number\n", h->mtime); if (unlink(fname) < 0 && errno != ENOENT && errno != EISDIR) eprintf("unlink %s:", fname); + tmp = strdup(fname); + mkdirp(dirname(tmp)); + free(tmp); + switch (h->type) { case REG: case AREG: