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