tar: Allow extracting only a given list of files
tar -xf foo.tar a b c
This commit is contained in:
parent
fde9e29d05
commit
258d0793ac
26
tar.c
26
tar.c
|
@ -313,26 +313,34 @@ sanitize(struct header *h)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xt(int (*fn)(char *, ssize_t, char[BLKSIZ]))
|
xt(int argc, char *argv[], int (*fn)(char *, ssize_t, char[BLKSIZ]))
|
||||||
{
|
{
|
||||||
char b[BLKSIZ], fname[256 + 1], *p;
|
char b[BLKSIZ], fname[256 + 1], *p;
|
||||||
struct header *h;
|
struct header *h = (struct header *)b;
|
||||||
long size;
|
long size;
|
||||||
int n;
|
int i, n;
|
||||||
|
|
||||||
h = (void *)b;
|
while (fread(b, BLKSIZ, 1, tarfile) == 1 && *h->name) {
|
||||||
|
sanitize(h), n = 0;
|
||||||
|
|
||||||
while (fread(b, BLKSIZ, 1, tarfile) == 1 && *(h->name)) {
|
/* small dance around non-null terminated fields */
|
||||||
sanitize(h);
|
|
||||||
n = 0;
|
|
||||||
if (h->prefix[0])
|
if (h->prefix[0])
|
||||||
n = snprintf(fname, sizeof(fname), "%.*s/",
|
n = snprintf(fname, sizeof(fname), "%.*s/",
|
||||||
(int)sizeof(h->prefix), h->prefix);
|
(int)sizeof(h->prefix), h->prefix);
|
||||||
snprintf(fname + n, sizeof(fname) - n, "%.*s",
|
snprintf(fname + n, sizeof(fname) - n, "%.*s",
|
||||||
(int)sizeof(h->name), h->name);
|
(int)sizeof(h->name), h->name);
|
||||||
|
|
||||||
|
if (argc) {
|
||||||
|
/* only extract the given files */
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
if (!strcmp(argv[i], fname))
|
||||||
|
break;
|
||||||
|
if (i == argc)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
|
if ((size = strtol(h->size, &p, 8)) < 0 || *p != '\0')
|
||||||
eprintf("strtol %s: invalid number\n", h->size);
|
eprintf("strtol %s: invalid number\n", h->size);
|
||||||
|
|
||||||
fn(fname, size, b);
|
fn(fname, size, b);
|
||||||
}
|
}
|
||||||
if (ferror(tarfile))
|
if (ferror(tarfile))
|
||||||
|
@ -430,7 +438,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
if (chdir(dir) < 0)
|
if (chdir(dir) < 0)
|
||||||
eprintf("chdir %s:", dir);
|
eprintf("chdir %s:", dir);
|
||||||
xt((mode == 'x') ? unarchive : print);
|
xt(argc, argv, (mode == 'x') ? unarchive : print);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user