summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/libarchive/libarchive/non-recursive-extract-and-list.patch
blob: cd7be5127aabcfa7d83ab6804723cb135b44aa02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
From 47f7566f6829c2b14e21bbbba699916de4998c72 Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Mon, 24 Oct 2016 12:54:48 +0200
Subject: [PATCH 1/1] non-recursive extract and list

Sometimes it makes sense to extract or list a directory contained in
an archive without also doing the same for the content of the
directory, i.e. allowing -n (= --no-recursion) in combination with the
x and t modes.

bsdtar uses the match functionality in libarchive to track include
matches. A new libarchive API call
archive_match_include_directories_recursively() gets introduced to
influence the matching behavior, with the default behavior as before.

Non-recursive matching can be achieved by anchoring the path match at
both start and end. Asking for a directory which itself isn't in the
archive when in non-recursive mode is an error and handled by the
existing mechanism for tracking unused inclusion entries.

Upstream-Status: Submitted [https://github.com/libarchive/libarchive/pull/812]

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>

---
 libarchive/archive.h       |  2 ++
 libarchive/archive_match.c | 30 +++++++++++++++++++++++++++++-
 tar/bsdtar.1               |  3 +--
 tar/bsdtar.c               | 12 ++++++++++--
 4 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/libarchive/archive.h b/libarchive/archive.h
index 32710201..59fb4aa6 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -1093,6 +1093,8 @@ __LA_DECL int	archive_match_excluded(struct archive *,
  */
 __LA_DECL int	archive_match_path_excluded(struct archive *,
 		    struct archive_entry *);
+/* Control recursive inclusion of directory content when directory is included. Default on. */
+__LA_DECL int	archive_match_include_directories_recursively(struct archive *, int _enabled);
 /* Add exclusion pathname pattern. */
 __LA_DECL int	archive_match_exclude_pattern(struct archive *, const char *);
 __LA_DECL int	archive_match_exclude_pattern_w(struct archive *,
diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c
index be72066e..bb6a3407 100644
--- a/libarchive/archive_match.c
+++ b/libarchive/archive_match.c
@@ -93,6 +93,9 @@ struct archive_match {
 	/* exclusion/inclusion set flag. */
 	int			 setflag;
 
+	/* Recursively include directory content? */
+	int			 recursive_include;
+
 	/*
 	 * Matching filename patterns.
 	 */
@@ -223,6 +226,7 @@ archive_match_new(void)
 		return (NULL);
 	a->archive.magic = ARCHIVE_MATCH_MAGIC;
 	a->archive.state = ARCHIVE_STATE_NEW;
+	a->recursive_include = 1;
 	match_list_init(&(a->inclusions));
 	match_list_init(&(a->exclusions));
 	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
@@ -471,6 +475,28 @@ archive_match_path_excluded(struct archive *_a,
 }
 
 /*
+ * When recursive inclusion of directory content is enabled,
+ * an inclusion pattern that matches a directory will also
+ * include everything beneath that directory. Enabled by default.
+ *
+ * For compatibility with GNU tar, exclusion patterns always
+ * match if a subset of the full patch matches (i.e., they are
+ * are not rooted at the beginning of the path) and thus there
+ * is no corresponding non-recursive exclusion mode.
+ */
+int
+archive_match_include_directories_recursively(struct archive *_a, int _enabled)
+{
+	struct archive_match *a;
+
+	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+	    ARCHIVE_STATE_NEW, "archive_match_include_directories_recursively");
+	a = (struct archive_match *)_a;
+	a->recursive_include = _enabled;
+	return (ARCHIVE_OK);
+}
+
+/*
  * Utility functions to get statistic information for inclusion patterns.
  */
 int
@@ -781,7 +807,9 @@ static int
 match_path_inclusion(struct archive_match *a, struct match *m,
     int mbs, const void *pn)
 {
-	int flag = PATHMATCH_NO_ANCHOR_END;
+	int flag = a->recursive_include ?
+		PATHMATCH_NO_ANCHOR_END : /* Prefix match is good enough. */
+		0; /* Full match required. */
 	int r;
 
 	if (mbs) {
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 132e1145..1dd2a847 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -386,8 +386,7 @@ and the default behavior in c, r, and u modes or if
 .Nm
 is run in x mode as root.
 .It Fl n , Fl Fl norecurse , Fl Fl no-recursion
-(c, r, u modes only)
-Do not recursively archive the contents of directories.
+Do not recursively archive (c, r, u), extract (x) or list (t) the contents of directories.
 .It Fl Fl newer Ar date
 (c, r, u modes only)
 Only include files and directories newer than the specified date.
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index 11dedbf9..d014cc3e 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -794,8 +794,6 @@ main(int argc, char **argv)
 			break;
 		}
 	}
-	if (bsdtar->flags & OPTFLAG_NO_SUBDIRS)
-		only_mode(bsdtar, "-n", "cru");
 	if (bsdtar->flags & OPTFLAG_STDOUT)
 		only_mode(bsdtar, "-O", "xt");
 	if (bsdtar->flags & OPTFLAG_UNLINK_FIRST)
@@ -845,6 +843,16 @@ main(int argc, char **argv)
 		only_mode(bsdtar, buff, "cru");
 	}
 
+	/*
+	 * When creating an archive from a directory tree, the directory
+	 * walking code will already avoid entering directories when
+	 * recursive inclusion of directory content is disabled, therefore
+	 * changing the matching behavior has no effect for creation modes.
+	 * It is relevant for extraction or listing.
+	 */
+	archive_match_include_directories_recursively(bsdtar->matching,
+						      !(bsdtar->flags & OPTFLAG_NO_SUBDIRS));
+
 	/* Filename "-" implies stdio. */
 	if (strcmp(bsdtar->filename, "-") == 0)
 		bsdtar->filename = NULL;
-- 
2.11.0