summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-06-15 05:55:41 +0000
committerkientzle <kientzle@FreeBSD.org>2004-06-15 05:55:41 +0000
commit5ace8b9fe9af8d4dd5140eb6dfac715032f55556 (patch)
treef5b7f5035df247695f901d5407f18939fb78784f /usr.bin/tar
parent292410a6b8e787b12658c7d87f2bbaeeb273723a (diff)
downloadFreeBSD-src-5ace8b9fe9af8d4dd5140eb6dfac715032f55556.zip
FreeBSD-src-5ace8b9fe9af8d4dd5140eb6dfac715032f55556.tar.gz
Add gtar-compatible -X/--exclude-from
Diffstat (limited to 'usr.bin/tar')
-rw-r--r--usr.bin/tar/bsdtar.c4
-rw-r--r--usr.bin/tar/bsdtar.h1
-rw-r--r--usr.bin/tar/matching.c38
3 files changed, 43 insertions, 0 deletions
diff --git a/usr.bin/tar/bsdtar.c b/usr.bin/tar/bsdtar.c
index f933cea..3221348 100644
--- a/usr.bin/tar/bsdtar.c
+++ b/usr.bin/tar/bsdtar.c
@@ -90,6 +90,7 @@ const struct option tar_longopts[] = {
{ "dereference", no_argument, NULL, 'L' },
{ "directory", required_argument, NULL, 'C' },
{ "exclude", required_argument, NULL, OPTION_EXCLUDE },
+ { "exclude-from", required_argument, NULL, 'X' },
{ "extract", no_argument, NULL, 'x' },
{ "fast-read", no_argument, NULL, OPTION_FAST_READ },
{ "file", required_argument, NULL, 'f' },
@@ -329,6 +330,9 @@ main(int argc, char **argv)
case 'w': /* SUSv2 */
bsdtar->option_interactive = 1;
break;
+ case 'X': /* GNU tar */
+ exclude_from_file(bsdtar, optarg);
+ break;
case 'x': /* SUSv2 */
if (mode != '\0')
bsdtar_errc(bsdtar, 1, 0,
diff --git a/usr.bin/tar/bsdtar.h b/usr.bin/tar/bsdtar.h
index 7cc7c5c..3c6746c 100644
--- a/usr.bin/tar/bsdtar.h
+++ b/usr.bin/tar/bsdtar.h
@@ -95,6 +95,7 @@ void bsdtar_strmode(struct archive_entry *entry, char *bp);
void bsdtar_warnc(struct bsdtar *, int _code, const char *fmt, ...);
void cleanup_exclusions(struct bsdtar *);
void exclude(struct bsdtar *, const char *pattern);
+void exclude_from_file(struct bsdtar *, const char *pathname);
int excluded(struct bsdtar *, const char *pathname);
void include(struct bsdtar *, const char *pattern);
void safe_fprintf(FILE *, const char *fmt, ...);
diff --git a/usr.bin/tar/matching.c b/usr.bin/tar/matching.c
index 2ba755f..da5417b 100644
--- a/usr.bin/tar/matching.c
+++ b/usr.bin/tar/matching.c
@@ -78,6 +78,44 @@ exclude(struct bsdtar *bsdtar, const char *pattern)
matching->exclusions_count++;
}
+/*
+ * Read lines from file and exclude() each one. This uses
+ * a self-sizing buffer to handle arbitrarily-long lines.
+ */
+void
+exclude_from_file(struct bsdtar *bsdtar, const char *pathname)
+{
+ FILE *f;
+ char *buff;
+ size_t buff_length, line_length;
+
+ f = fopen(pathname, "r");
+ if (f == NULL)
+ bsdtar_errc(bsdtar, 1, errno, "Couldn't open %s", pathname);
+ buff_length = 256;
+ buff = malloc(buff_length);
+ if (buff == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read %s", pathname);
+ while(fgets(buff, buff_length, f) != NULL) {
+ line_length = strlen(buff);
+ while (buff[line_length - 1] != '\n') {
+ buff = realloc(buff, buff_length *= 2);
+ if (buff == NULL)
+ bsdtar_errc(bsdtar, 1, ENOMEM,
+ "Line too long in %s", pathname);
+ if (fgets(buff + line_length,
+ buff_length - line_length, f) == NULL)
+ bsdtar_errc(bsdtar, 1, 0,
+ "Bad input line in %s", pathname);
+ line_length = strlen(buff);
+ }
+ buff[line_length - 1] = '\0';
+ exclude(bsdtar, buff);
+ }
+ free(buff);
+ fclose(f);
+}
+
void
include(struct bsdtar *bsdtar, const char *pattern)
{
OpenPOWER on IntegriCloud