~sergei.glushchenko/+junk/page-scan-hack

« back to all changes in this revision

Viewing changes to src/libarchive/libarchive/archive_util.c

merge parallel compression branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2009 Michihiro NAKAJIMA
 
3
 * Copyright (c) 2003-2007 Tim Kientzle
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
18
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "archive_platform.h"
 
28
__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
 
29
 
 
30
#ifdef HAVE_SYS_TYPES_H
 
31
#include <sys/types.h>
 
32
#endif
 
33
#ifdef HAVE_STDLIB_H
 
34
#include <stdlib.h>
 
35
#endif
 
36
#ifdef HAVE_STRING_H
 
37
#include <string.h>
 
38
#endif
 
39
 
 
40
#include "archive.h"
 
41
#include "archive_private.h"
 
42
#include "archive_string.h"
 
43
 
 
44
#if ARCHIVE_VERSION_NUMBER < 3000000
 
45
/* These disappear in libarchive 3.0 */
 
46
/* Deprecated. */
 
47
int
 
48
archive_api_feature(void)
 
49
{
 
50
        return (ARCHIVE_API_FEATURE);
 
51
}
 
52
 
 
53
/* Deprecated. */
 
54
int
 
55
archive_api_version(void)
 
56
{
 
57
        return (ARCHIVE_API_VERSION);
 
58
}
 
59
 
 
60
/* Deprecated synonym for archive_version_number() */
 
61
int
 
62
archive_version_stamp(void)
 
63
{
 
64
        return (archive_version_number());
 
65
}
 
66
 
 
67
/* Deprecated synonym for archive_version_string() */
 
68
const char *
 
69
archive_version(void)
 
70
{
 
71
        return (archive_version_string());
 
72
}
 
73
#endif
 
74
 
 
75
int
 
76
archive_version_number(void)
 
77
{
 
78
        return (ARCHIVE_VERSION_NUMBER);
 
79
}
 
80
 
 
81
const char *
 
82
archive_version_string(void)
 
83
{
 
84
        return (ARCHIVE_VERSION_STRING);
 
85
}
 
86
 
 
87
int
 
88
archive_errno(struct archive *a)
 
89
{
 
90
        return (a->archive_error_number);
 
91
}
 
92
 
 
93
const char *
 
94
archive_error_string(struct archive *a)
 
95
{
 
96
 
 
97
        if (a->error != NULL  &&  *a->error != '\0')
 
98
                return (a->error);
 
99
        else
 
100
                return ("(Empty error message)");
 
101
}
 
102
 
 
103
int
 
104
archive_file_count(struct archive *a)
 
105
{
 
106
        return (a->file_count);
 
107
}
 
108
 
 
109
int
 
110
archive_format(struct archive *a)
 
111
{
 
112
        return (a->archive_format);
 
113
}
 
114
 
 
115
const char *
 
116
archive_format_name(struct archive *a)
 
117
{
 
118
        return (a->archive_format_name);
 
119
}
 
120
 
 
121
 
 
122
int
 
123
archive_compression(struct archive *a)
 
124
{
 
125
        return (a->compression_code);
 
126
}
 
127
 
 
128
const char *
 
129
archive_compression_name(struct archive *a)
 
130
{
 
131
        return (a->compression_name);
 
132
}
 
133
 
 
134
 
 
135
/*
 
136
 * Return a count of the number of compressed bytes processed.
 
137
 */
 
138
int64_t
 
139
archive_position_compressed(struct archive *a)
 
140
{
 
141
        return (a->raw_position);
 
142
}
 
143
 
 
144
/*
 
145
 * Return a count of the number of uncompressed bytes processed.
 
146
 */
 
147
int64_t
 
148
archive_position_uncompressed(struct archive *a)
 
149
{
 
150
        return (a->file_position);
 
151
}
 
152
 
 
153
void
 
154
archive_clear_error(struct archive *a)
 
155
{
 
156
        archive_string_empty(&a->error_string);
 
157
        a->error = NULL;
 
158
}
 
159
 
 
160
void
 
161
archive_set_error(struct archive *a, int error_number, const char *fmt, ...)
 
162
{
 
163
        va_list ap;
 
164
 
 
165
        a->archive_error_number = error_number;
 
166
        if (fmt == NULL) {
 
167
                a->error = NULL;
 
168
                return;
 
169
        }
 
170
 
 
171
        va_start(ap, fmt);
 
172
        archive_string_vsprintf(&(a->error_string), fmt, ap);
 
173
        va_end(ap);
 
174
        a->error = a->error_string.s;
 
175
}
 
176
 
 
177
void
 
178
archive_copy_error(struct archive *dest, struct archive *src)
 
179
{
 
180
        dest->archive_error_number = src->archive_error_number;
 
181
 
 
182
        archive_string_copy(&dest->error_string, &src->error_string);
 
183
        dest->error = dest->error_string.s;
 
184
}
 
185
 
 
186
void
 
187
__archive_errx(int retvalue, const char *msg)
 
188
{
 
189
        static const char *msg1 = "Fatal Internal Error in libarchive: ";
 
190
        size_t s;
 
191
 
 
192
        s = write(2, msg1, strlen(msg1));
 
193
        (void)s; /* UNUSED */
 
194
        s = write(2, msg, strlen(msg));
 
195
        (void)s; /* UNUSED */
 
196
        s = write(2, "\n", 1);
 
197
        (void)s; /* UNUSED */
 
198
        exit(retvalue);
 
199
}
 
200
 
 
201
/*
 
202
 * Parse option strings
 
203
 *  Detail of option format.
 
204
 *    - The option can accept:
 
205
 *     "opt-name", "!opt-name", "opt-name=value".
 
206
 *
 
207
 *    - The option entries are separated by comma.
 
208
 *        e.g  "compression=9,opt=XXX,opt-b=ZZZ"
 
209
 *
 
210
 *    - The name of option string consist of '-' and alphabet
 
211
 *      but character '-' cannot be used for the first character.
 
212
 *      (Regular expression is [a-z][-a-z]+)
 
213
 *
 
214
 *    - For a specfic format/filter, using the format name with ':'.
 
215
 *        e.g  "zip:compression=9"
 
216
 *        (This "compression=9" option entry is for "zip" format only)
 
217
 *
 
218
 *      If another entries follow it, those are not for
 
219
 *      the specfic format/filter.
 
220
 *        e.g  handle "zip:compression=9,opt=XXX,opt-b=ZZZ"
 
221
 *          "zip" format/filter handler will get "compression=9"
 
222
 *          all format/filter handler will get "opt=XXX"
 
223
 *          all format/filter handler will get "opt-b=ZZZ"
 
224
 *
 
225
 *    - Whitespace and tab are bypassed.
 
226
 *
 
227
 */
 
228
int
 
229
__archive_parse_options(const char *p, const char *fn, int keysize, char *key,
 
230
    int valsize, char *val)
 
231
{
 
232
        const char *p_org;
 
233
        int apply;
 
234
        int kidx, vidx;
 
235
        int negative; 
 
236
        enum {
 
237
                /* Requested for initialization. */
 
238
                INIT,
 
239
                /* Finding format/filter-name and option-name. */
 
240
                F_BOTH,
 
241
                /* Finding option-name only.
 
242
                 * (already detected format/filter-name) */
 
243
                F_NAME,
 
244
                /* Getting option-value. */
 
245
                G_VALUE,
 
246
        } state;
 
247
 
 
248
        p_org = p;
 
249
        state = INIT;
 
250
        kidx = vidx = negative = 0;
 
251
        apply = 1;
 
252
        while (*p) {
 
253
                switch (state) {
 
254
                case INIT:
 
255
                        kidx = vidx = 0;
 
256
                        negative = 0;
 
257
                        apply = 1;
 
258
                        state = F_BOTH;
 
259
                        break;
 
260
                case F_BOTH:
 
261
                case F_NAME:
 
262
                        if ((*p >= 'a' && *p <= 'z') ||
 
263
                            (*p >= '0' && *p <= '9') || *p == '-') {
 
264
                                if (kidx == 0 && !(*p >= 'a' && *p <= 'z'))
 
265
                                        /* Illegal sequence. */
 
266
                                        return (-1);
 
267
                                if (kidx >= keysize -1)
 
268
                                        /* Too many characters. */
 
269
                                        return (-1);
 
270
                                key[kidx++] = *p++;
 
271
                        } else if (*p == '!') {
 
272
                                if (kidx != 0)
 
273
                                        /* Illegal sequence. */
 
274
                                        return (-1);
 
275
                                negative = 1;
 
276
                                ++p;
 
277
                        } else if (*p == ',') {
 
278
                                if (kidx == 0)
 
279
                                        /* Illegal sequence. */
 
280
                                        return (-1);
 
281
                                if (!negative)
 
282
                                        val[vidx++] = '1';
 
283
                                /* We have got boolean option data. */
 
284
                                ++p;
 
285
                                if (apply)
 
286
                                        goto complete;
 
287
                                else
 
288
                                        /* This option does not apply to the
 
289
                                         * format which the fn variable
 
290
                                         * indicate. */
 
291
                                        state = INIT;
 
292
                        } else if (*p == ':') {
 
293
                                /* obuf data is format name */
 
294
                                if (state == F_NAME)
 
295
                                        /* We already found it. */
 
296
                                        return (-1);
 
297
                                if (kidx == 0)
 
298
                                        /* Illegal sequence. */
 
299
                                        return (-1);
 
300
                                if (negative)
 
301
                                        /* We cannot accept "!format-name:". */
 
302
                                        return (-1);
 
303
                                key[kidx] = '\0';
 
304
                                if (strcmp(fn, key) != 0)
 
305
                                        /* This option does not apply to the
 
306
                                         * format which the fn variable
 
307
                                         * indicate. */
 
308
                                        apply = 0;
 
309
                                kidx = 0;
 
310
                                ++p;
 
311
                                state = F_NAME;
 
312
                        } else if (*p == '=') {
 
313
                                if (kidx == 0)
 
314
                                        /* Illegal sequence. */
 
315
                                        return (-1);
 
316
                                if (negative)
 
317
                                        /* We cannot accept "!opt-name=value". */
 
318
                                        return (-1);
 
319
                                ++p;
 
320
                                state = G_VALUE;
 
321
                        } else if (*p == ' ') {
 
322
                                /* Pass the space character */
 
323
                                ++p;
 
324
                        } else {
 
325
                                /* Illegal character. */
 
326
                                return (-1);
 
327
                        }
 
328
                        break;
 
329
                case G_VALUE:
 
330
                        if (*p == ',') {
 
331
                                if (vidx == 0)
 
332
                                        /* Illegal sequence. */
 
333
                                        return (-1);
 
334
                                /* We have got option data. */
 
335
                                ++p;
 
336
                                if (apply)
 
337
                                        goto complete;
 
338
                                else
 
339
                                        /* This option does not apply to the
 
340
                                         * format which the fn variable
 
341
                                         * indicate. */
 
342
                                        state = INIT;
 
343
                        } else if (*p == ' ') {
 
344
                                /* Pass the space character */
 
345
                                ++p;
 
346
                        } else {
 
347
                                if (vidx >= valsize -1)
 
348
                                        /* Too many characters. */
 
349
                                        return (-1);
 
350
                                val[vidx++] = *p++;
 
351
                        }
 
352
                        break;
 
353
                } 
 
354
        }
 
355
 
 
356
        switch (state) {
 
357
        case F_BOTH:
 
358
        case F_NAME:
 
359
                if (kidx != 0) {
 
360
                        if (!negative)
 
361
                                val[vidx++] = '1';
 
362
                        /* We have got boolean option. */
 
363
                        if (apply)
 
364
                                /* This option apply to the format which the
 
365
                                 * fn variable indicate. */
 
366
                                goto complete;
 
367
                }
 
368
                break;
 
369
        case G_VALUE:
 
370
                if (vidx == 0)
 
371
                        /* Illegal sequence. */
 
372
                        return (-1);
 
373
                /* We have got option value. */
 
374
                if (apply)
 
375
                        /* This option apply to the format which the fn
 
376
                         * variable indicate. */
 
377
                        goto complete;
 
378
                break;
 
379
        case INIT:/* nothing */
 
380
                break;
 
381
        }
 
382
 
 
383
        /* End of Option string. */
 
384
        return (0);
 
385
 
 
386
complete:
 
387
        key[kidx] = '\0';
 
388
        val[vidx] = '\0';
 
389
        /* Return a size which we've consumed for detecting option */
 
390
        return ((int)(p - p_org));
 
391
}