diff options
Diffstat (limited to 'contrib/libarchive/tar/subst.c')
-rw-r--r-- | contrib/libarchive/tar/subst.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/contrib/libarchive/tar/subst.c b/contrib/libarchive/tar/subst.c index 765f74b..b592fe0 100644 --- a/contrib/libarchive/tar/subst.c +++ b/contrib/libarchive/tar/subst.c @@ -44,7 +44,7 @@ struct subst_rule { struct subst_rule *next; regex_t re; char *result; - unsigned int global:1, print:1, symlink:1; + unsigned int global:1, print:1, regular:1, symlink:1, hardlink:1; }; struct substitution { @@ -117,9 +117,12 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) memcpy(rule->result, start_subst, end_pattern - start_subst); rule->result[end_pattern - start_subst] = '\0'; - rule->global = 0; - rule->print = 0; - rule->symlink = 0; + /* Defaults */ + rule->global = 0; /* Don't do multiple replacements. */ + rule->print = 0; /* Don't print. */ + rule->regular = 1; /* Rewrite regular filenames. */ + rule->symlink = 1; /* Rewrite symlink targets. */ + rule->hardlink = 1; /* Rewrite hardlink targets. */ while (*++end_pattern) { switch (*end_pattern) { @@ -127,14 +130,28 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) case 'G': rule->global = 1; break; + case 'h': + rule->hardlink = 1; + break; + case 'H': + rule->hardlink = 0; + break; case 'p': case 'P': rule->print = 1; break; + case 'r': + rule->regular = 1; + break; + case 'R': + rule->regular = 0; + break; case 's': - case 'S': rule->symlink = 1; break; + case 'S': + rule->symlink = 0; + break; default: lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern); } @@ -155,7 +172,8 @@ realloc_strncat(char **str, const char *append, size_t len) new_str = malloc(old_len + len + 1); if (new_str == NULL) lafe_errc(1, errno, "Out of memory"); - memcpy(new_str, *str, old_len); + if (*str != NULL) + memcpy(new_str, *str, old_len); memcpy(new_str + old_len, append, len); new_str[old_len + len] = '\0'; free(*str); @@ -176,14 +194,16 @@ realloc_strcat(char **str, const char *append) new_str = malloc(old_len + strlen(append) + 1); if (new_str == NULL) lafe_errc(1, errno, "Out of memory"); - memcpy(new_str, *str, old_len); + if (*str != NULL) + memcpy(new_str, *str, old_len); strcpy(new_str + old_len, append); free(*str); *str = new_str; } int -apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int symlink_only) +apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, + int symlink_target, int hardlink_target) { const char *path = name; regmatch_t matches[10]; @@ -201,8 +221,17 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int s print_match = 0; for (rule = subst->first_rule; rule != NULL; rule = rule->next) { - if (symlink_only && !rule->symlink) - continue; + if (symlink_target) { + if (!rule->symlink) + continue; + } else if (hardlink_target) { + if (!rule->hardlink) + continue; + } else { /* Regular filename. */ + if (!rule->regular) + continue; + } + if (regexec(&rule->re, name, 10, matches, 0)) continue; @@ -213,7 +242,9 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int s 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_eo); + realloc_strncat(result, + name + matches[0].rm_so, + matches[0].rm_eo - matches[0].rm_so); j = i + 1; continue; } |