547 lines
11 KiB
Diff
547 lines
11 KiB
Diff
lib/decode.c | 2 +-
|
|
lib/extract.c | 94 +++++++++++++++++++++++++++++++++++++++++++------------
|
|
lib/handle.c | 1 +
|
|
lib/wrapper.c | 12 ++++++-
|
|
libtar/libtar.c | 30 +++++++++++------
|
|
5 files changed, 106 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/lib/decode.c b/lib/decode.c
|
|
index 794c868..c2c2baa 100644
|
|
--- a/lib/decode.c
|
|
+++ b/lib/decode.c
|
|
@@ -29,7 +29,7 @@ th_get_pathname(TAR *t)
|
|
char filename[MAXPATHLEN];
|
|
|
|
if (t->th_buf.gnu_longname)
|
|
- return t->th_buf.gnu_longname;
|
|
+ return strdup(t->th_buf.gnu_longname);
|
|
|
|
if (t->th_buf.prefix[0] != '\0')
|
|
{
|
|
diff --git a/lib/extract.c b/lib/extract.c
|
|
index cacfe58..8993b95 100644
|
|
--- a/lib/extract.c
|
|
+++ b/lib/extract.c
|
|
@@ -44,9 +44,10 @@ tar_set_file_perms(TAR *t, char *realname)
|
|
uid_t uid;
|
|
gid_t gid;
|
|
struct utimbuf ut;
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
uid = th_get_uid(t);
|
|
gid = th_get_gid(t);
|
|
@@ -69,6 +70,7 @@ tar_set_file_perms(TAR *t, char *realname)
|
|
filename, uid, gid, strerror(errno));
|
|
# endif
|
|
#endif /* HAVE_LCHOWN */
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
@@ -78,6 +80,7 @@ tar_set_file_perms(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("utime()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
@@ -87,9 +90,11 @@ tar_set_file_perms(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("chmod()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -168,7 +173,7 @@ tar_extract_regfile(TAR *t, char *realname)
|
|
int fdout;
|
|
int i, k;
|
|
char buf[T_BLOCKSIZE];
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
#ifdef DEBUG
|
|
printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t,
|
|
@@ -181,14 +186,18 @@ tar_extract_regfile(TAR *t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
size = th_get_size(t);
|
|
uid = th_get_uid(t);
|
|
gid = th_get_gid(t);
|
|
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
#ifdef DEBUG
|
|
printf(" ==> extracting: %s (mode %04o, uid %d, gid %d, %d bytes)\n",
|
|
@@ -204,6 +213,7 @@ tar_extract_regfile(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("open()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
@@ -235,23 +245,30 @@ tar_extract_regfile(TAR *t, char *realname)
|
|
{
|
|
if (k != -1)
|
|
errno = EINVAL;
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
/* write block to output file */
|
|
if (write(fdout, buf,
|
|
((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
}
|
|
|
|
/* close output file */
|
|
if (close(fdout) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
#ifdef DEBUG
|
|
printf("### done extracting %s\n", filename);
|
|
#endif
|
|
-
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -290,7 +307,7 @@ tar_skip_regfile(TAR *t)
|
|
int
|
|
tar_extract_hardlink(TAR * t, char *realname)
|
|
{
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
char *linktgt = NULL;
|
|
linkname_t *lnp;
|
|
libtar_hashptr_t hp;
|
|
@@ -301,9 +318,13 @@ tar_extract_hardlink(TAR * t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
libtar_hashptr_reset(&hp);
|
|
if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
|
|
(libtar_matchfunc_t)libtar_str_match) != 0)
|
|
@@ -322,9 +343,11 @@ tar_extract_hardlink(TAR * t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("link()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -333,7 +356,7 @@ tar_extract_hardlink(TAR * t, char *realname)
|
|
int
|
|
tar_extract_symlink(TAR *t, char *realname)
|
|
{
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
if (!TH_ISSYM(t))
|
|
{
|
|
@@ -341,9 +364,13 @@ tar_extract_symlink(TAR *t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
if (unlink(filename) == -1 && errno != ENOENT)
|
|
return -1;
|
|
@@ -357,9 +384,11 @@ tar_extract_symlink(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("symlink()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -370,7 +399,7 @@ tar_extract_chardev(TAR *t, char *realname)
|
|
{
|
|
mode_t mode;
|
|
unsigned long devmaj, devmin;
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
if (!TH_ISCHR(t))
|
|
{
|
|
@@ -378,14 +407,18 @@ tar_extract_chardev(TAR *t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
devmaj = th_get_devmajor(t);
|
|
devmin = th_get_devminor(t);
|
|
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
-
|
|
+ }
|
|
+
|
|
#ifdef DEBUG
|
|
printf(" ==> extracting: %s (character device %ld,%ld)\n",
|
|
filename, devmaj, devmin);
|
|
@@ -396,9 +429,11 @@ tar_extract_chardev(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("mknod()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -409,7 +444,7 @@ tar_extract_blockdev(TAR *t, char *realname)
|
|
{
|
|
mode_t mode;
|
|
unsigned long devmaj, devmin;
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
if (!TH_ISBLK(t))
|
|
{
|
|
@@ -417,13 +452,17 @@ tar_extract_blockdev(TAR *t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
devmaj = th_get_devmajor(t);
|
|
devmin = th_get_devminor(t);
|
|
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
#ifdef DEBUG
|
|
printf(" ==> extracting: %s (block device %ld,%ld)\n",
|
|
@@ -435,9 +474,11 @@ tar_extract_blockdev(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("mknod()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -447,19 +488,22 @@ int
|
|
tar_extract_dir(TAR *t, char *realname)
|
|
{
|
|
mode_t mode;
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
if (!TH_ISDIR(t))
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
-
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
#ifdef DEBUG
|
|
printf(" ==> extracting: %s (mode %04o, directory)\n", filename,
|
|
@@ -474,6 +518,7 @@ tar_extract_dir(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("chmod()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
else
|
|
@@ -481,6 +526,7 @@ tar_extract_dir(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
puts(" *** using existing directory");
|
|
#endif
|
|
+ free (pn);
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -489,10 +535,12 @@ tar_extract_dir(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("mkdir()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
}
|
|
-
|
|
+
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
@@ -502,7 +550,7 @@ int
|
|
tar_extract_fifo(TAR *t, char *realname)
|
|
{
|
|
mode_t mode;
|
|
- char *filename;
|
|
+ char *filename,*pn;
|
|
|
|
if (!TH_ISFIFO(t))
|
|
{
|
|
@@ -510,11 +558,15 @@ tar_extract_fifo(TAR *t, char *realname)
|
|
return -1;
|
|
}
|
|
|
|
- filename = (realname ? realname : th_get_pathname(t));
|
|
+ pn = th_get_pathname(t);
|
|
+ filename = (realname ? realname : pn);
|
|
mode = th_get_mode(t);
|
|
|
|
if (mkdirhier(dirname(filename)) == -1)
|
|
+ {
|
|
+ free (pn);
|
|
return -1;
|
|
+ }
|
|
|
|
#ifdef DEBUG
|
|
printf(" ==> extracting: %s (fifo)\n", filename);
|
|
@@ -524,9 +576,11 @@ tar_extract_fifo(TAR *t, char *realname)
|
|
#ifdef DEBUG
|
|
perror("mkfifo()");
|
|
#endif
|
|
+ free (pn);
|
|
return -1;
|
|
}
|
|
|
|
+ free (pn);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/lib/handle.c b/lib/handle.c
|
|
index ae974b9..e3a48cb 100644
|
|
--- a/lib/handle.c
|
|
+++ b/lib/handle.c
|
|
@@ -82,6 +82,7 @@ tar_open(TAR **t, char *pathname, tartype_t *type,
|
|
(*t)->fd = (*((*t)->type->openfunc))(pathname, oflags, mode);
|
|
if ((*t)->fd == -1)
|
|
{
|
|
+ libtar_hash_free((*t)->h, NULL);
|
|
free(*t);
|
|
return -1;
|
|
}
|
|
diff --git a/lib/wrapper.c b/lib/wrapper.c
|
|
index 51d5086..e60a530 100644
|
|
--- a/lib/wrapper.c
|
|
+++ b/lib/wrapper.c
|
|
@@ -36,7 +36,10 @@ tar_extract_glob(TAR *t, char *globname, char *prefix)
|
|
if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD))
|
|
{
|
|
if (TH_ISREG(t) && tar_skip_regfile(t))
|
|
+ {
|
|
+ free (filename);
|
|
return -1;
|
|
+ }
|
|
continue;
|
|
}
|
|
if (t->options & TAR_VERBOSE)
|
|
@@ -46,7 +49,11 @@ tar_extract_glob(TAR *t, char *globname, char *prefix)
|
|
else
|
|
strlcpy(buf, filename, sizeof(buf));
|
|
if (tar_extract_file(t, filename) != 0)
|
|
+ {
|
|
+ free (filename);
|
|
return -1;
|
|
+ }
|
|
+ free (filename);
|
|
}
|
|
|
|
return (i == 1 ? 0 : -1);
|
|
@@ -77,13 +84,16 @@ tar_extract_all(TAR *t, char *prefix)
|
|
snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
|
|
else
|
|
strlcpy(buf, filename, sizeof(buf));
|
|
- free(filename);
|
|
#ifdef DEBUG
|
|
printf(" tar_extract_all(): calling tar_extract_file(t, "
|
|
"\"%s\")\n", buf);
|
|
#endif
|
|
if (tar_extract_file(t, buf) != 0)
|
|
+ {
|
|
+ free (filename);
|
|
return -1;
|
|
+ }
|
|
+ free (filename);
|
|
}
|
|
|
|
return (i == 1 ? 0 : -1);
|
|
diff --git a/libtar/libtar.c b/libtar/libtar.c
|
|
index a6cef72..f06c5b8 100644
|
|
--- a/libtar/libtar.c
|
|
+++ b/libtar/libtar.c
|
|
@@ -249,7 +249,9 @@ extract(char *tarfile, char *rootdir)
|
|
#endif
|
|
if (tar_extract_all(t, rootdir) != 0)
|
|
{
|
|
+
|
|
fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
|
|
+ tar_close(t);
|
|
return -1;
|
|
}
|
|
|
|
@@ -267,12 +269,13 @@ extract(char *tarfile, char *rootdir)
|
|
|
|
|
|
void
|
|
-usage()
|
|
+usage(void *rootdir)
|
|
{
|
|
printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
|
|
progname);
|
|
printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
|
|
progname);
|
|
+ free(rootdir);
|
|
exit(-1);
|
|
}
|
|
|
|
@@ -289,6 +292,7 @@ main(int argc, char *argv[])
|
|
int c;
|
|
int mode = 0;
|
|
libtar_list_t *l;
|
|
+ int return_code = -2;
|
|
|
|
progname = basename(argv[0]);
|
|
|
|
@@ -310,17 +314,17 @@ main(int argc, char *argv[])
|
|
break;
|
|
case 'c':
|
|
if (mode)
|
|
- usage();
|
|
+ usage(rootdir);
|
|
mode = MODE_CREATE;
|
|
break;
|
|
case 'x':
|
|
if (mode)
|
|
- usage();
|
|
+ usage(rootdir);
|
|
mode = MODE_EXTRACT;
|
|
break;
|
|
case 't':
|
|
if (mode)
|
|
- usage();
|
|
+ usage(rootdir);
|
|
mode = MODE_LIST;
|
|
break;
|
|
#ifdef HAVE_LIBZ
|
|
@@ -329,7 +333,7 @@ main(int argc, char *argv[])
|
|
break;
|
|
#endif /* HAVE_LIBZ */
|
|
default:
|
|
- usage();
|
|
+ usage(rootdir);
|
|
}
|
|
|
|
if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
|
|
@@ -338,7 +342,7 @@ main(int argc, char *argv[])
|
|
printf("argc - optind == %d\tmode == %d\n", argc - optind,
|
|
mode);
|
|
#endif
|
|
- usage();
|
|
+ usage(rootdir);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
@@ -348,21 +352,25 @@ main(int argc, char *argv[])
|
|
switch (mode)
|
|
{
|
|
case MODE_EXTRACT:
|
|
- return extract(argv[optind], rootdir);
|
|
+ return_code = extract(argv[optind], rootdir);
|
|
+ break;
|
|
case MODE_CREATE:
|
|
tarfile = argv[optind];
|
|
l = libtar_list_new(LIST_QUEUE, NULL);
|
|
for (c = optind + 1; c < argc; c++)
|
|
libtar_list_add(l, argv[c]);
|
|
- return create(tarfile, rootdir, l);
|
|
+ return_code = create(tarfile, rootdir, l);
|
|
+ libtar_list_free (l, NULL);
|
|
+ break;
|
|
case MODE_LIST:
|
|
- return list(argv[optind]);
|
|
+ return_code = list(argv[optind]);
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
- /* NOTREACHED */
|
|
- return -2;
|
|
+ free(rootdir);
|
|
+ return return_code;
|
|
}
|
|
|
|
|