summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar/read.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2005-03-13 04:12:30 +0000
committerkientzle <kientzle@FreeBSD.org>2005-03-13 04:12:30 +0000
commit0eac7627b850b8c334a8046f449e923e3b71300f (patch)
treedfe7c2c3a1342845144bb340f0a5527b3e3fa7ce /usr.bin/tar/read.c
parent83b23d92b11796798d75702703ef2ea0aed23259 (diff)
downloadFreeBSD-src-0eac7627b850b8c334a8046f449e923e3b71300f.zip
FreeBSD-src-0eac7627b850b8c334a8046f449e923e3b71300f.tar.gz
Add --strip-components option, per bin/77666.
Thanks to: Sangwoo Shim
Diffstat (limited to 'usr.bin/tar/read.c')
-rw-r--r--usr.bin/tar/read.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/usr.bin/tar/read.c b/usr.bin/tar/read.c
index 0e478a1..1bb657e 100644
--- a/usr.bin/tar/read.c
+++ b/usr.bin/tar/read.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include "bsdtar.h"
static void cleanup_security(struct bsdtar *);
+static int edit_pathname(struct bsdtar *, struct archive_entry *);
static void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode);
@@ -115,9 +116,29 @@ read_archive(struct bsdtar *bsdtar, char mode)
continue;
}
+ /*
+ * Note that exclusions are checked before pathname
+ * rewrites are handled. This gives more control over
+ * exclusions, since rewrites always lose information.
+ * (For example, consider a rewrite s/foo[0-9]/foo/.
+ * If we check exclusions after the rewrite, there
+ * would be no way to exclude foo1/bar while allowing
+ * foo2/bar.)
+ */
if (excluded(bsdtar, archive_entry_pathname(entry)))
continue;
+ /*
+ * Modify the pathname as requested by the user. We
+ * do this for -t as well to give users a way to
+ * preview the effects of their rewrites. We also do
+ * this before extraction security checks (including
+ * leading '/' removal). Note that some rewrite
+ * failures prevent extraction.
+ */
+ if (edit_pathname(bsdtar, entry))
+ continue;
+
if (mode == 't') {
/* Perversely, gtar uses -O to mean "send to stderr"
* when used with -t. */
@@ -295,6 +316,43 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
}
+/*
+ * Handle --strip-components and any future path-rewriting options.
+ * Returns non-zero if the pathname should not be extracted.
+ */
+static int
+edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
+{
+ /* Strip leading dir names as per --strip-components option. */
+ if (bsdtar->strip_components > 0) {
+ int r = bsdtar->strip_components;
+ const char *name = archive_entry_pathname(entry);
+ const char *p = name;
+ char *q;
+
+ while (r > 0) {
+ switch (*p++) {
+ case '/':
+ r--;
+ name = p;
+ break;
+ case '\0':
+ /* Path is too short, skip it. */
+ return (1);
+ }
+ }
+ /* Safely replace name in archive_entry. */
+ q = strdup(name);
+ archive_entry_copy_pathname(entry, q);
+ free(q);
+ }
+
+ return (0);
+}
+
+/*
+ * Structure for storing path of last successful security check.
+ */
struct security {
char *path;
size_t path_size;
OpenPOWER on IntegriCloud