]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Apply global flag in substitution 634/head
authorSean Farley <sean+dev@farley.org>
Sun, 3 Jan 2016 21:42:00 +0000 (16:42 -0500)
committerSean Farley <sean+dev@farley.org>
Sun, 3 Jan 2016 21:42:00 +0000 (16:42 -0500)
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.

tar/subst.c
tar/test/test_option_s.c

index fd6f8e222c6a79c87f37335340650e9d8ff7e621..4710e06a623a81b0609efc76745cf8a0dab13988 100644 (file)
@@ -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)
index a1f8697e32b2cd94c52b09c76010af169e50feb1..ee8332f34fd5873fc7ed0ef541d3dd90a3b5ea92 100644 (file)
@@ -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");
 }