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