~laurynas-biveinis/percona-xtrabackup/xtrabackup-page-filters

« back to all changes in this revision

Viewing changes to src/libarchive/tar/subst.c

merge parallel compression branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2008 Joerg Sonnenberger
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
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.
 
13
 *
 
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.
 
24
 */
 
25
 
 
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 $");
 
28
 
 
29
#if HAVE_REGEX_H
 
30
#include "bsdtar.h"
 
31
 
 
32
#include <errno.h>
 
33
#include <regex.h>
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
 
 
37
#ifndef REG_BASIC
 
38
#define REG_BASIC 0
 
39
#endif
 
40
 
 
41
#include "err.h"
 
42
 
 
43
struct subst_rule {
 
44
        struct subst_rule *next;
 
45
        regex_t re;
 
46
        char *result;
 
47
        unsigned int global:1, print:1, symlink:1;
 
48
};
 
49
 
 
50
struct substitution {
 
51
        struct subst_rule *first_rule, *last_rule;
 
52
};
 
53
 
 
54
static void
 
55
init_substitution(struct bsdtar *bsdtar)
 
56
{
 
57
        struct substitution *subst;
 
58
 
 
59
        bsdtar->substitution = subst = malloc(sizeof(*subst));
 
60
        if (subst == NULL)
 
61
                lafe_errc(1, errno, "Out of memory");
 
62
        subst->first_rule = subst->last_rule = NULL;
 
63
}
 
64
 
 
65
void
 
66
add_substitution(struct bsdtar *bsdtar, const char *rule_text)
 
67
{
 
68
        struct subst_rule *rule;
 
69
        struct substitution *subst;
 
70
        const char *end_pattern, *start_subst;
 
71
        char *pattern;
 
72
        int r;
 
73
 
 
74
        if ((subst = bsdtar->substitution) == NULL) {
 
75
                init_substitution(bsdtar);
 
76
                subst = bsdtar->substitution;
 
77
        }
 
78
 
 
79
        rule = malloc(sizeof(*rule));
 
80
        if (rule == NULL)
 
81
                lafe_errc(1, errno, "Out of memory");
 
82
        rule->next = NULL;
 
83
 
 
84
        if (subst->last_rule == NULL)
 
85
                subst->first_rule = rule;
 
86
        else
 
87
                subst->last_rule->next = rule;
 
88
        subst->last_rule = rule;
 
89
 
 
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");
 
95
 
 
96
        pattern = malloc(end_pattern - rule_text);
 
97
        if (pattern == NULL)
 
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';
 
101
 
 
102
        if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) {
 
103
                char buf[80];
 
104
                regerror(r, &rule->re, buf, sizeof(buf));
 
105
                lafe_errc(1, 0, "Invalid regular expression: %s", buf);
 
106
        }
 
107
        free(pattern);
 
108
 
 
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");
 
113
 
 
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';
 
119
 
 
120
        rule->global = 0;
 
121
        rule->print = 0;
 
122
        rule->symlink = 0;
 
123
 
 
124
        while (*++end_pattern) {
 
125
                switch (*end_pattern) {
 
126
                case 'g':
 
127
                case 'G':
 
128
                        rule->global = 1;
 
129
                        break;
 
130
                case 'p':
 
131
                case 'P':
 
132
                        rule->print = 1;
 
133
                        break;
 
134
                case 's':
 
135
                case 'S':
 
136
                        rule->symlink = 1;
 
137
                        break;
 
138
                default:
 
139
                        lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
 
140
                }
 
141
        }
 
142
}
 
143
 
 
144
static void
 
145
realloc_strncat(char **str, const char *append, size_t len)
 
146
{
 
147
        char *new_str;
 
148
        size_t old_len;
 
149
 
 
150
        if (*str == NULL)
 
151
                old_len = 0;
 
152
        else
 
153
                old_len = strlen(*str);
 
154
 
 
155
        new_str = malloc(old_len + len + 1);
 
156
        if (new_str == NULL)
 
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';
 
161
        free(*str);
 
162
        *str = new_str;
 
163
}
 
164
 
 
165
static void
 
166
realloc_strcat(char **str, const char *append)
 
167
{
 
168
        char *new_str;
 
169
        size_t old_len;
 
170
 
 
171
        if (*str == NULL)
 
172
                old_len = 0;
 
173
        else
 
174
                old_len = strlen(*str);
 
175
 
 
176
        new_str = malloc(old_len + strlen(append) + 1);
 
177
        if (new_str == NULL)
 
178
                lafe_errc(1, errno, "Out of memory");
 
179
        memcpy(new_str, *str, old_len);
 
180
        strcpy(new_str + old_len, append);
 
181
        free(*str);
 
182
        *str = new_str;
 
183
}
 
184
 
 
185
int
 
186
apply_substitution(struct bsdtar *bsdtar, const char *name, char **result, int symlink_only)
 
187
{
 
188
        const char *path = name;
 
189
        regmatch_t matches[10];
 
190
        size_t i, j;
 
191
        struct subst_rule *rule;
 
192
        struct substitution *subst;
 
193
        int c, got_match, print_match;
 
194
 
 
195
        *result = NULL;
 
196
 
 
197
        if ((subst = bsdtar->substitution) == NULL)
 
198
                return 0;
 
199
 
 
200
        got_match = 0;
 
201
        print_match = 0;
 
202
 
 
203
        for (rule = subst->first_rule; rule != NULL; rule = rule->next) {
 
204
                if (symlink_only && !rule->symlink)
 
205
                        continue;
 
206
                if (regexec(&rule->re, name, 10, matches, 0))
 
207
                        continue;
 
208
 
 
209
                got_match = 1;
 
210
                print_match |= rule->print;
 
211
                realloc_strncat(result, name, matches[0].rm_so);
 
212
 
 
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);
 
217
                                j = i + 1;
 
218
                                continue;
 
219
                        }
 
220
                        if (rule->result[i] != '\\')
 
221
                                continue;
 
222
 
 
223
                        ++i;
 
224
                        c = rule->result[i];
 
225
                        switch (c) {
 
226
                        case '~':
 
227
                        case '\\':
 
228
                                realloc_strncat(result, rule->result + j, i - j - 1);
 
229
                                j = i;
 
230
                                break;
 
231
                        case '1':
 
232
                        case '2':
 
233
                        case '3':
 
234
                        case '4':
 
235
                        case '5':
 
236
                        case '6':
 
237
                        case '7':
 
238
                        case '8':
 
239
                        case '9':
 
240
                                realloc_strncat(result, rule->result + j, i - j - 1);
 
241
                                if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
 
242
                                        free(*result);
 
243
                                        *result = NULL;
 
244
                                        return -1;
 
245
                                }
 
246
                                realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
 
247
                                j = i + 1;
 
248
                                break;
 
249
                        default:
 
250
                                /* Just continue; */
 
251
                                break;
 
252
                        }
 
253
 
 
254
                }
 
255
 
 
256
                realloc_strcat(result, rule->result + j);
 
257
 
 
258
                name += matches[0].rm_eo;
 
259
 
 
260
                if (!rule->global)
 
261
                        break;
 
262
        }
 
263
 
 
264
        if (got_match)
 
265
                realloc_strcat(result, name);
 
266
 
 
267
        if (print_match)
 
268
                fprintf(stderr, "%s >> %s\n", path, *result);
 
269
 
 
270
        return got_match;
 
271
}
 
272
 
 
273
void
 
274
cleanup_substitution(struct bsdtar *bsdtar)
 
275
{
 
276
        struct subst_rule *rule;
 
277
        struct substitution *subst;
 
278
 
 
279
        if ((subst = bsdtar->substitution) == NULL)
 
280
                return;
 
281
 
 
282
        while ((rule = subst->first_rule) != NULL) {
 
283
                subst->first_rule = rule->next;
 
284
                free(rule->result);
 
285
                free(rule);
 
286
        }
 
287
        free(subst);
 
288
}
 
289
#endif /* HAVE_REGEX_H */