From: Sean Farley Date: Sun, 3 Jan 2016 21:42:00 +0000 (-0500) Subject: Apply global flag in substitution X-Git-Tag: v3.1.900a~31^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F634%2Fhead;p=thirdparty%2Flibarchive.git Apply global flag in substitution Add loop to move through a path name looking for additional matches if the global flag is provided for a substitution. The loop breaks when no more matches are found for the rule. Previously, the global flag would end up advancing to the next rule instead of searching farther into the path for another match. --- diff --git a/tar/subst.c b/tar/subst.c index fd6f8e222..4710e06a6 100644 --- a/tar/subst.c +++ b/tar/subst.c @@ -236,64 +236,66 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, continue; } - if (regexec(&rule->re, name, 10, matches, 0)) - continue; - - got_match = 1; - print_match |= rule->print; - realloc_strncat(result, name, matches[0].rm_so); - - for (i = 0, j = 0; rule->result[i] != '\0'; ++i) { - if (rule->result[i] == '~') { - realloc_strncat(result, rule->result + j, i - j); - realloc_strncat(result, - name + matches[0].rm_so, - matches[0].rm_eo - matches[0].rm_so); - j = i + 1; - continue; - } - if (rule->result[i] != '\\') - continue; - - ++i; - c = rule->result[i]; - switch (c) { - case '~': - case '\\': - realloc_strncat(result, rule->result + j, i - j - 1); - j = i; + while (1) { + if (regexec(&rule->re, name, 10, matches, 0)) break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - realloc_strncat(result, rule->result + j, i - j - 1); - if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) { - free(*result); - *result = NULL; - return -1; + + got_match = 1; + print_match |= rule->print; + realloc_strncat(result, name, matches[0].rm_so); + + for (i = 0, j = 0; rule->result[i] != '\0'; ++i) { + if (rule->result[i] == '~') { + realloc_strncat(result, rule->result + j, i - j); + realloc_strncat(result, + name + matches[0].rm_so, + matches[0].rm_eo - matches[0].rm_so); + j = i + 1; + continue; + } + if (rule->result[i] != '\\') + continue; + + ++i; + c = rule->result[i]; + switch (c) { + case '~': + case '\\': + realloc_strncat(result, rule->result + j, i - j - 1); + j = i; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + realloc_strncat(result, rule->result + j, i - j - 1); + if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) { + free(*result); + *result = NULL; + return -1; + } + realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so); + j = i + 1; + break; + default: + /* Just continue; */ + break; } - realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so); - j = i + 1; - break; - default: - /* Just continue; */ - break; - } - } + } - realloc_strcat(result, rule->result + j); + realloc_strcat(result, rule->result + j); - name += matches[0].rm_eo; + name += matches[0].rm_eo; - if (!rule->global) - break; + if (!rule->global) + break; + } } if (got_match) diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c index a1f8697e3..ee8332f34 100644 --- a/tar/test/test_option_s.c +++ b/tar/test/test_option_s.c @@ -82,9 +82,9 @@ DEFINE_TEST(test_option_s) */ assertMakeDir("test4", 0755); systemf("%s -cf test4.tar in/d1/foo in/d1/bar", - testprog, testprog); + testprog); systemf("%s -xf test4.tar -s /foo/bar/ -s }bar}baz} -C test4", - testprog, testprog); + testprog); assertFileContents("foo", 3, "test4/in/d1/bar"); assertFileContents("bar", 3, "test4/in/d1/baz"); @@ -258,4 +258,23 @@ DEFINE_TEST(test_option_s) assertFileContents("foo", 3, "test13a/in/d1/hardlink2"); assertIsHardlink("test13a/in/d1/foo", "test13a/in/d1/hardlink2"); /* TODO: See above; expand this test to verify renames at creation. */ + + /* + * Test 14: Global substitutions when extracting archive. + */ + /* Global substitution. */ + assertMakeDir("test14", 0755); + systemf("%s -cf test14.tar in/d1/foo in/d1/bar", + testprog); + systemf("%s -xf test14.tar -s /o/z/g -s /bar/baz/ -C test14", + testprog); + assertFileContents("foo", 3, "test14/in/d1/fzz"); + assertFileContents("bar", 3, "test14/in/d1/baz"); + /* Singular substitution. */ + systemf("%s -cf test14.tar in/d1/foo in/d1/bar", + testprog); + systemf("%s -xf test14.tar -s /o/z/ -s /bar/baz/ -C test14", + testprog); + assertFileContents("foo", 3, "test14/in/d1/fzo"); + assertFileContents("bar", 3, "test14/in/d1/baz"); }