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;
}