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 $");
42 struct subst_rule
*next
;
45 unsigned int global
:1, print
:1, symlink
:1;
49 struct subst_rule
*first_rule
, *last_rule
;
53 init_substitution(struct bsdtar
*bsdtar
)
55 struct substitution
*subst
;
57 bsdtar
->substitution
= subst
= malloc(sizeof(*subst
));
59 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
60 subst
->first_rule
= subst
->last_rule
= NULL
;
64 add_substitution(struct bsdtar
*bsdtar
, const char *rule_text
)
66 struct subst_rule
*rule
;
67 struct substitution
*subst
;
68 const char *end_pattern
, *start_subst
;
72 if ((subst
= bsdtar
->substitution
) == NULL
) {
73 init_substitution(bsdtar
);
74 subst
= bsdtar
->substitution
;
77 rule
= malloc(sizeof(*rule
));
79 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
82 if (subst
->last_rule
== NULL
)
83 subst
->first_rule
= rule
;
85 subst
->last_rule
->next
= rule
;
86 subst
->last_rule
= rule
;
88 if (*rule_text
== '\0')
89 bsdtar_errc(bsdtar
, 1, 0, "Empty replacement string");
90 end_pattern
= strchr(rule_text
+ 1, *rule_text
);
91 if (end_pattern
== NULL
)
92 bsdtar_errc(bsdtar
, 1, 0, "Invalid replacement string");
94 pattern
= malloc(end_pattern
- rule_text
);
96 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
97 memcpy(pattern
, rule_text
+ 1, end_pattern
- rule_text
- 1);
98 pattern
[end_pattern
- rule_text
- 1] = '\0';
100 if ((r
= regcomp(&rule
->re
, pattern
, REG_BASIC
)) != 0) {
102 regerror(r
, &rule
->re
, buf
, sizeof(buf
));
103 bsdtar_errc(bsdtar
, 1, 0, "Invalid regular expression: %s", buf
);
107 start_subst
= end_pattern
+ 1;
108 end_pattern
= strchr(start_subst
, *rule_text
);
109 if (end_pattern
== NULL
)
110 bsdtar_errc(bsdtar
, 1, 0, "Invalid replacement string");
112 rule
->result
= malloc(end_pattern
- start_subst
+ 1);
113 if (rule
->result
== NULL
)
114 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
115 memcpy(rule
->result
, start_subst
, end_pattern
- start_subst
);
116 rule
->result
[end_pattern
- start_subst
] = '\0';
122 while (*++end_pattern
) {
123 switch (*end_pattern
) {
137 bsdtar_errc(bsdtar
, 1, 0, "Invalid replacement flag %c", *end_pattern
);
143 realloc_strncat(struct bsdtar
*bsdtar
, char **str
, const char *append
, size_t len
)
151 old_len
= strlen(*str
);
153 new_str
= malloc(old_len
+ len
+ 1);
155 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
156 memcpy(new_str
, *str
, old_len
);
157 memcpy(new_str
+ old_len
, append
, len
);
158 new_str
[old_len
+ len
] = '\0';
164 realloc_strcat(struct bsdtar
*bsdtar
, char **str
, const char *append
)
172 old_len
= strlen(*str
);
174 new_str
= malloc(old_len
+ strlen(append
) + 1);
176 bsdtar_errc(bsdtar
, 1, errno
, "Out of memory");
177 memcpy(new_str
, *str
, old_len
);
178 strcpy(new_str
+ old_len
, append
);
184 apply_substitution(struct bsdtar
*bsdtar
, const char *name
, char **result
, int symlink_only
)
186 const char *path
= name
;
187 regmatch_t matches
[10];
189 struct subst_rule
*rule
;
190 struct substitution
*subst
;
191 int c
, got_match
, print_match
;
195 if ((subst
= bsdtar
->substitution
) == NULL
)
201 for (rule
= subst
->first_rule
; rule
!= NULL
; rule
= rule
->next
) {
202 if (symlink_only
&& !rule
->symlink
)
204 if (regexec(&rule
->re
, name
, 10, matches
, 0))
208 print_match
|= rule
->print
;
209 realloc_strncat(bsdtar
, result
, name
, matches
[0].rm_so
);
211 for (i
= 0, j
= 0; rule
->result
[i
] != '\0'; ++i
) {
212 if (rule
->result
[i
] == '~') {
213 realloc_strncat(bsdtar
, result
, rule
->result
+ j
, i
- j
);
214 realloc_strncat(bsdtar
, result
, name
, matches
[0].rm_eo
);
218 if (rule
->result
[i
] != '\\')
226 realloc_strncat(bsdtar
, result
, rule
->result
+ j
, i
- j
- 1);
238 realloc_strncat(bsdtar
, result
, rule
->result
+ j
, i
- j
- 1);
239 if ((size_t)(c
- '0') > (size_t)(rule
->re
.re_nsub
)) {
244 realloc_strncat(bsdtar
, result
, name
+ matches
[c
- '0'].rm_so
, matches
[c
- '0'].rm_eo
- matches
[c
- '0'].rm_so
);
254 realloc_strcat(bsdtar
, result
, rule
->result
+ j
);
256 name
+= matches
[0].rm_eo
;
263 realloc_strcat(bsdtar
, result
, name
);
266 fprintf(stderr
, "%s >> %s\n", path
, *result
);
272 cleanup_substitution(struct bsdtar
*bsdtar
)
274 struct subst_rule
*rule
;
275 struct substitution
*subst
;
277 if ((subst
= bsdtar
->substitution
) == NULL
)
280 while ((rule
= subst
->first_rule
) != NULL
) {
281 subst
->first_rule
= rule
->next
;
287 #endif /* HAVE_REGEX_H */