From 97905f699111f114218b736ccd3979bce3095d9d Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 20 Apr 2015 16:31:51 +0100 Subject: [PATCH] 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. --- tar.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tar.c b/tar.c index afe7854..d680d46 100644 --- a/tar.c +++ b/tar.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -172,6 +173,29 @@ archive(const char *path) return 0; } +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]) { @@ -179,13 +203,17 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ]) 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: