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 */