tar: Add support for -z and -j by invoking external programs
Only extraction is supported at the moment.
This commit is contained in:
parent
d00d73fd4a
commit
7fbb858bcd
252
tar.c
252
tar.c
|
@ -1,13 +1,14 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -52,104 +53,40 @@ static FILE *tarfile;
|
||||||
static ino_t tarinode;
|
static ino_t tarinode;
|
||||||
static dev_t tardev;
|
static dev_t tardev;
|
||||||
|
|
||||||
static int mflag = 0;
|
static int mflag;
|
||||||
|
static char filtermode;
|
||||||
|
|
||||||
static void
|
static FILE *
|
||||||
usage(void)
|
decomp(FILE *fp)
|
||||||
{
|
{
|
||||||
eprintf("usage: tar [-f tarfile] [-C dir] [-]x[m]|t\n"
|
int fds[2];
|
||||||
" tar [-f tarfile] [-C dir] [-]c dir\n"
|
pid_t pid;
|
||||||
" tar [-C dir] cf tarfile dir\n"
|
|
||||||
" tar [-C dir] x[m]|tf tarfile\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
if (pipe(fds) < 0)
|
||||||
main(int argc, char *argv[])
|
eprintf("pipe:");
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
char *file = NULL, *dir = ".", *ap;
|
|
||||||
char mode = '\0';
|
|
||||||
|
|
||||||
ARGBEGIN {
|
pid = fork();
|
||||||
case 'x':
|
if (pid < 0) {
|
||||||
case 'c':
|
eprintf("fork:");
|
||||||
case 't':
|
} else if (!pid) {
|
||||||
if (mode)
|
dup2(fileno(fp), 0);
|
||||||
usage();
|
dup2(fds[1], 1);
|
||||||
mode = ARGC();
|
close(fds[0]);
|
||||||
break;
|
close(fds[1]);
|
||||||
case 'C':
|
|
||||||
dir = EARGF(usage());
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
file = EARGF(usage());
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
mflag = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
} ARGEND;
|
|
||||||
|
|
||||||
if (!mode) {
|
switch (filtermode) {
|
||||||
if (argc < 1)
|
case 'j':
|
||||||
usage();
|
execlp("bzip2", "bzip2", "-cd", (char *)0);
|
||||||
|
eprintf("execlp bzip2:");
|
||||||
for (ap = argv[0]; *ap; ap++) {
|
case 'z':
|
||||||
switch (*ap) {
|
execlp("gzip", "gzip", "-cdf", (char *)0);
|
||||||
case 'x':
|
eprintf("execlp gzip:");
|
||||||
case 'c':
|
|
||||||
case 't':
|
|
||||||
if (mode)
|
|
||||||
usage();
|
|
||||||
mode = *ap;
|
|
||||||
break;
|
break;
|
||||||
case 'f':
|
|
||||||
if (argc < 2)
|
|
||||||
usage();
|
|
||||||
argc--, argv++;
|
|
||||||
file = argv[0];
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
if (argc < 2)
|
|
||||||
usage();
|
|
||||||
argc--, argv++;
|
|
||||||
dir = argv[0];
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
mflag = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argc--, argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mode || argc != (mode == 'c'))
|
close(fds[1]);
|
||||||
usage();
|
return fdopen(fds[0], "r");
|
||||||
|
|
||||||
if (file) {
|
|
||||||
tarfile = fopen(file, (mode == 'c') ? "wb" : "rb");
|
|
||||||
if (!tarfile)
|
|
||||||
eprintf("tar: open '%s':", file);
|
|
||||||
if (lstat(file, &st) < 0)
|
|
||||||
eprintf("tar: stat '%s':", file);
|
|
||||||
tarinode = st.st_ino;
|
|
||||||
tardev = st.st_dev;
|
|
||||||
} else {
|
|
||||||
tarfile = (mode == 'c') ? stdout : stdin;
|
|
||||||
}
|
|
||||||
|
|
||||||
chdir(dir);
|
|
||||||
|
|
||||||
if (mode == 'c') {
|
|
||||||
c(argv[0]);
|
|
||||||
} else {
|
|
||||||
xt((mode == 'x') ? unarchive : print);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -330,3 +267,134 @@ xt(int (*fn)(char*, int, char[Blksiz]))
|
||||||
fn(fname, strtol(h->size, 0, 8), b);
|
fn(fname, strtol(h->size, 0, 8), b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
eprintf("usage: tar [-f tarfile] [-C dir] [-]j|z [-]x[m]|t\n"
|
||||||
|
" tar [-f tarfile] [-C dir] [-]c dir\n"
|
||||||
|
" tar [-C dir] cf tarfile dir\n"
|
||||||
|
" tar [-C dir] j|z x[m]|tf tarfile\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
char *file = NULL, *dir = ".", *ap;
|
||||||
|
char mode = '\0';
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
case 'x':
|
||||||
|
case 'c':
|
||||||
|
case 't':
|
||||||
|
if (mode)
|
||||||
|
usage();
|
||||||
|
mode = ARGC();
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
dir = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
file = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mflag = 1;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
case 'z':
|
||||||
|
if (filtermode)
|
||||||
|
usage();
|
||||||
|
filtermode = ARGC();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
} ARGEND;
|
||||||
|
|
||||||
|
if (!mode) {
|
||||||
|
if (argc < 1)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
for (ap = argv[0]; *ap; ap++) {
|
||||||
|
switch (*ap) {
|
||||||
|
case 'x':
|
||||||
|
case 'c':
|
||||||
|
case 't':
|
||||||
|
if (mode)
|
||||||
|
usage();
|
||||||
|
mode = *ap;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
argc--, argv++;
|
||||||
|
file = argv[0];
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
argc--, argv++;
|
||||||
|
dir = argv[0];
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mflag = 1;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
case 'z':
|
||||||
|
if (filtermode)
|
||||||
|
usage();
|
||||||
|
filtermode = *ap;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc--, argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mode || argc != (mode == 'c'))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 'c':
|
||||||
|
if (file) {
|
||||||
|
if (!(fp = fopen(file, "wb")))
|
||||||
|
eprintf("fopen %s:", file);
|
||||||
|
if (lstat(file, &st) < 0)
|
||||||
|
eprintf("tar: stat '%s':", file);
|
||||||
|
tarinode = st.st_ino;
|
||||||
|
tardev = st.st_dev;
|
||||||
|
tarfile = fp;
|
||||||
|
} else {
|
||||||
|
tarfile = stdout;
|
||||||
|
}
|
||||||
|
chdir(dir);
|
||||||
|
c(argv[0]);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
case 'x':
|
||||||
|
if (file) {
|
||||||
|
if (!(fp = fopen(file, "rb")))
|
||||||
|
eprintf("fopen %s:", file);
|
||||||
|
} else {
|
||||||
|
fp = stdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (filtermode) {
|
||||||
|
case 'j':
|
||||||
|
case 'z':
|
||||||
|
tarfile = decomp(fp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tarfile = fp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(dir);
|
||||||
|
xt(mode == 'x' ? unarchive : print);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user