sbase

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

commit 97905f699111f114218b736ccd3979bce3095d9d
parent 3ef6d4e4c97c937e82b873399d76900ebb498389
Author: sin <sin@2f30.org>
Date:   Mon, 20 Apr 2015 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:
Mtar.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: