~ubuntu-branches/ubuntu/quantal/cmake/quantal

« back to all changes in this revision

Viewing changes to Utilities/cmlibarchive/tar/subst.c

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2012-04-30 12:14:32 UTC
  • mfrom: (3.1.30 sid)
  • Revision ID: package-import@ubuntu.com-20120430121432-rqh2fjl3zcblehh5
Tags: 2.8.8-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add xfail_compiler_flag.diff: Mark compiler flag tests as expected
    failures.
  - Add ubuntu_qt_import_dir_variable.diff: define QT_IMPORTS_DIR even
    when that dir does not exist.
* Remove increase_ctest_test_timeout.diff, merged upstream.

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