2
* Copyright (c) 2008 Joerg Sonnenberger
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
#include "bsdtar_platform.h"
27
__FBSDID("$FreeBSD: src/usr.bin/tar/subst.c,v 1.4 2008/06/15 10:08:16 kientzle Exp $");
44
struct subst_rule *next;
47
unsigned int global:1, print:1, symlink:1;
51
struct subst_rule *first_rule, *last_rule;
55
init_substitution(struct bsdtar *bsdtar)
57
struct substitution *subst;
59
bsdtar->substitution = subst = malloc(sizeof(*subst));
61
lafe_errc(1, errno, "Out of memory");
62
subst->first_rule = subst->last_rule = NULL;
66
add_substitution(struct bsdtar *bsdtar, const char *rule_text)
68
struct subst_rule *rule;
69
struct substitution *subst;
70
const char *end_pattern, *start_subst;
74
if ((subst = bsdtar->substitution) == NULL) {
75
init_substitution(bsdtar);
76
subst = bsdtar->substitution;
79
rule = malloc(sizeof(*rule));
81
lafe_errc(1, errno, "Out of memory");
84
if (subst->last_rule == NULL)
85
subst->first_rule = rule;
87
subst->last_rule->next = rule;
88
subst->last_rule = rule;
90
if (*rule_text == '\0')
91
lafe_errc(1, 0, "Empty replacement string");
92
end_pattern = strchr(rule_text + 1, *rule_text);
93
if (end_pattern == NULL)
94
lafe_errc(1, 0, "Invalid replacement string");
96
pattern = malloc(end_pattern - rule_text);
98
lafe_errc(1, errno, "Out of memory");
99
memcpy(pattern, rule_text + 1, end_pattern - rule_text - 1);
100
pattern[end_pattern - rule_text - 1] = '\0';
102
if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) {
104
regerror(r, &rule->re, buf, sizeof(buf));
105
lafe_errc(1, 0, "Invalid regular expression: %s", buf);
109
start_subst = end_pattern + 1;
110
end_pattern = strchr(start_subst, *rule_text);
111
if (end_pattern == NULL)
112
lafe_errc(1, 0, "Invalid replacement string");
114
rule->result = malloc(end_pattern - start_subst + 1);
115
if (rule->result == NULL)
116
lafe_errc(1, errno, "Out of memory");
117
memcpy(rule->result, start_subst, end_pattern - start_subst);
118
rule->result[end_pattern - start_subst] = '\0';
124
while (*++end_pattern) {
125
switch (*end_pattern) {
139
lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
145
realloc_strncat(char **str, const char *append, size_t len)
153
old_len = strlen(*str);
155
new_str = malloc(old_len + len + 1);
157
lafe_errc(1, errno, "Out of memory");
158
memcpy(new_str, *str, old_len);
159
memcpy(new_str + old_len, append, len);
160
new_str[old_len + len] = '\0';
166
realloc_strcat(char **str, const char *append)
174
old_len = strlen(*str);
176
new_str = malloc(old_len + strlen(append) + 1);
178
lafe_errc(1, errno, "Out of memory");
179
memcpy(new_str, *str, old_len);
180
strcpy(new_str + old_len, append);
186
apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int symlink_only)
188
const char *path = name;
189
regmatch_t matches[10];
191
struct subst_rule *rule;
192
struct substitution *subst;
193
int c, got_match, print_match;
197
if ((subst = bsdtar->substitution) == NULL)
203
for (rule = subst->first_rule; rule != NULL; rule = rule->next) {
204
if (symlink_only && !rule->symlink)
206
if (regexec(&rule->re, name, 10, matches, 0))
210
print_match |= rule->print;
211
realloc_strncat(result, name, matches[0].rm_so);
213
for (i = 0, j = 0; rule->result[i] != '\0'; ++i) {
214
if (rule->result[i] == '~') {
215
realloc_strncat(result, rule->result + j, i - j);
216
realloc_strncat(result, name, matches[0].rm_eo);
220
if (rule->result[i] != '\\')
228
realloc_strncat(result, rule->result + j, i - j - 1);
240
realloc_strncat(result, rule->result + j, i - j - 1);
241
if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
246
realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
256
realloc_strcat(result, rule->result + j);
258
name += matches[0].rm_eo;
265
realloc_strcat(result, name);
268
fprintf(stderr, "%s >> %s\n", path, *result);
274
cleanup_substitution(struct bsdtar *bsdtar)
276
struct subst_rule *rule;
277
struct substitution *subst;
279
if ((subst = bsdtar->substitution) == NULL)
282
while ((rule = subst->first_rule) != NULL) {
283
subst->first_rule = rule->next;
289
#endif /* HAVE_REGEX_H */