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.
This commit is contained in:
sin 2015-04-20 16:31:51 +01:00
parent 3ef6d4e4c9
commit 97905f6991
1 changed files with 29 additions and 1 deletions

30
tar.c
View File

@ -4,6 +4,7 @@
#include <errno.h>
#include <grp.h>
#include <libgen.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@ -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: