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: