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
archive_api_feature(void)48 archive_api_feature(void)
49 {
50 return (ARCHIVE_API_FEATURE);
51 }
52
53 /* Deprecated. */
54 int
archive_api_version(void)55 archive_api_version(void)
56 {
57 return (ARCHIVE_API_VERSION);
58 }
59
60 /* Deprecated synonym for archive_version_number() */
61 int
archive_version_stamp(void)62 archive_version_stamp(void)
63 {
64 return (archive_version_number());
65 }
66
67 /* Deprecated synonym for archive_version_string() */
68 const char *
archive_version(void)69 archive_version(void)
70 {
71 return (archive_version_string());
72 }
73 #endif
74
75 int
archive_version_number(void)76 archive_version_number(void)
77 {
78 return (ARCHIVE_VERSION_NUMBER);
79 }
80
81 const char *
archive_version_string(void)82 archive_version_string(void)
83 {
84 return (ARCHIVE_VERSION_STRING);
85 }
86
87 int
archive_errno(struct archive * a)88 archive_errno(struct archive *a)
89 {
90 return (a->archive_error_number);
91 }
92
93 const char *
archive_error_string(struct archive * a)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
archive_file_count(struct archive * a)104 archive_file_count(struct archive *a)
105 {
106 return (a->file_count);
107 }
108
109 int
archive_format(struct archive * a)110 archive_format(struct archive *a)
111 {
112 return (a->archive_format);
113 }
114
115 const char *
archive_format_name(struct archive * a)116 archive_format_name(struct archive *a)
117 {
118 return (a->archive_format_name);
119 }
120
121
122 int
archive_compression(struct archive * a)123 archive_compression(struct archive *a)
124 {
125 return (a->compression_code);
126 }
127
128 const char *
archive_compression_name(struct archive * a)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
archive_position_compressed(struct archive * a)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
archive_position_uncompressed(struct archive * a)148 archive_position_uncompressed(struct archive *a)
149 {
150 return (a->file_position);
151 }
152
153 void
archive_clear_error(struct archive * a)154 archive_clear_error(struct archive *a)
155 {
156 archive_string_empty(&a->error_string);
157 a->error = NULL;
158 }
159
160 void
archive_set_error(struct archive * a,int error_number,const char * fmt,...)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
archive_copy_error(struct archive * dest,struct archive * src)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
__archive_errx(int retvalue,const char * msg)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
__archive_parse_options(const char * p,const char * fn,int keysize,char * key,int valsize,char * val)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 }
392