archive_options.c revision 232153
1231200Smm/*-
2231200Smm * Copyright (c) 2011 Tim Kientzle
3231200Smm * All rights reserved.
4231200Smm *
5231200Smm * Redistribution and use in source and binary forms, with or without
6231200Smm * modification, are permitted provided that the following conditions
7231200Smm * are met:
8231200Smm * 1. Redistributions of source code must retain the above copyright
9231200Smm *    notice, this list of conditions and the following disclaimer.
10231200Smm * 2. Redistributions in binary form must reproduce the above copyright
11231200Smm *    notice, this list of conditions and the following disclaimer in the
12231200Smm *    documentation and/or other materials provided with the distribution.
13231200Smm *
14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24231200Smm */
25231200Smm
26231200Smm#include "archive_platform.h"
27231200Smm__FBSDID("$FreeBSD$");
28231200Smm
29231200Smm#include "archive_options_private.h"
30231200Smm
31231200Smmstatic const char *
32231200Smmparse_option(const char **str,
33231200Smm    const char **mod, const char **opt, const char **val);
34231200Smm
35231200Smmint
36231200Smm_archive_set_option(struct archive *a,
37231200Smm    const char *m, const char *o, const char *v,
38231200Smm    int magic, const char *fn, option_handler use_option)
39231200Smm{
40231200Smm	const char *mp, *op, *vp;
41232153Smm	int r;
42231200Smm
43231200Smm	archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
44231200Smm
45231200Smm	mp = m != NULL && m[0] == '\0' ? NULL : m;
46231200Smm	op = o != NULL && o[0] == '\0' ? NULL : o;
47231200Smm	vp = v != NULL && v[0] == '\0' ? NULL : v;
48231200Smm
49231200Smm	if (op == NULL && vp == NULL)
50231200Smm		return (ARCHIVE_OK);
51232153Smm	if (op == NULL) {
52232153Smm		archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
53231200Smm		return (ARCHIVE_FAILED);
54232153Smm	}
55231200Smm
56232153Smm	r = use_option(a, mp, op, vp);
57232153Smm	if (r == ARCHIVE_WARN - 1) {
58232153Smm		archive_set_error(a, ARCHIVE_ERRNO_MISC,
59232153Smm		    "Unknown module name: `%s'", mp);
60232153Smm		return (ARCHIVE_FAILED);
61232153Smm	}
62232153Smm	if (r == ARCHIVE_WARN) {
63232153Smm		archive_set_error(a, ARCHIVE_ERRNO_MISC,
64232153Smm		    "Undefined option: `%s%s%s%s%s%s'",
65232153Smm		    vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
66232153Smm		return (ARCHIVE_FAILED);
67232153Smm	}
68232153Smm	return (r);
69231200Smm}
70231200Smm
71231200Smmint
72231200Smm_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v,
73231200Smm    option_handler use_format_option, option_handler use_filter_option)
74231200Smm{
75231200Smm	int r1, r2;
76231200Smm
77231200Smm	if (o == NULL && v == NULL)
78231200Smm		return (ARCHIVE_OK);
79231200Smm	if (o == NULL)
80231200Smm		return (ARCHIVE_FAILED);
81231200Smm
82231200Smm	r1 = use_format_option(a, m, o, v);
83231200Smm	if (r1 == ARCHIVE_FATAL)
84231200Smm		return (ARCHIVE_FATAL);
85231200Smm
86231200Smm	r2 = use_filter_option(a, m, o, v);
87231200Smm	if (r2 == ARCHIVE_FATAL)
88231200Smm		return (ARCHIVE_FATAL);
89231200Smm
90231200Smm	return r1 > r2 ? r1 : r2;
91231200Smm}
92231200Smm
93231200Smmint
94231200Smm_archive_set_options(struct archive *a, const char *options,
95231200Smm    int magic, const char *fn, option_handler use_option)
96231200Smm{
97231200Smm	int allok = 1, anyok = 0, r;
98231200Smm	char *data;
99231200Smm	const char *s, *mod, *opt, *val;
100231200Smm
101231200Smm	archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
102231200Smm
103231200Smm	if (options == NULL || options[0] == '\0')
104231200Smm		return ARCHIVE_OK;
105231200Smm
106231200Smm	data = (char *)malloc(strlen(options) + 1);
107231200Smm	strcpy(data, options);
108231200Smm	s = (const char *)data;
109231200Smm
110231200Smm	do {
111231200Smm		mod = opt = val = NULL;
112231200Smm
113231200Smm		parse_option(&s, &mod, &opt, &val);
114231200Smm
115231200Smm		r = use_option(a, mod, opt, val);
116231200Smm		if (r == ARCHIVE_FATAL) {
117231200Smm			free(data);
118231200Smm			return (ARCHIVE_FATAL);
119231200Smm		}
120232153Smm		if (r == ARCHIVE_FAILED && mod != NULL) {
121232153Smm			free(data);
122232153Smm			return (ARCHIVE_FAILED);
123232153Smm		}
124232153Smm		if (r == ARCHIVE_WARN - 1) {
125232153Smm			/* The module name is wrong. */
126232153Smm			archive_set_error(a, ARCHIVE_ERRNO_MISC,
127232153Smm			    "Unknown module name: `%s'", mod);
128232153Smm			free(data);
129232153Smm			return (ARCHIVE_FAILED);
130232153Smm		}
131232153Smm		if (r == ARCHIVE_WARN) {
132232153Smm			/* The option name is wrong. No-one used this. */
133232153Smm			archive_set_error(a, ARCHIVE_ERRNO_MISC,
134232153Smm			    "Undefined option: `%s%s%s'",
135232153Smm			    mod?mod:"", mod?":":"", opt);
136232153Smm			free(data);
137232153Smm			return (ARCHIVE_FAILED);
138232153Smm		}
139231200Smm		if (r == ARCHIVE_OK)
140231200Smm			anyok = 1;
141231200Smm		else
142231200Smm			allok = 0;
143231200Smm	} while (s != NULL);
144231200Smm
145231200Smm	free(data);
146231200Smm	return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED;
147231200Smm}
148231200Smm
149231200Smmstatic const char *
150231200Smmparse_option(const char **s, const char **m, const char **o, const char **v)
151231200Smm{
152231200Smm	const char *end, *mod, *opt, *val;
153231200Smm	char *p;
154231200Smm
155231200Smm	end = NULL;
156231200Smm	mod = NULL;
157231200Smm	opt = *s;
158231200Smm	val = "1";
159231200Smm
160231200Smm	p = strchr(opt, ',');
161231200Smm
162231200Smm	if (p != NULL) {
163231200Smm		*p = '\0';
164231200Smm		end = ((const char *)p) + 1;
165231200Smm	}
166231200Smm
167231200Smm	if (0 == strlen(opt)) {
168231200Smm		*s = end;
169231200Smm		*m = NULL;
170231200Smm		*o = NULL;
171231200Smm		*v = NULL;
172231200Smm		return end;
173231200Smm	}
174231200Smm
175231200Smm	p = strchr(opt, ':');
176231200Smm	if (p != NULL) {
177231200Smm		*p = '\0';
178231200Smm		mod = opt;
179231200Smm		opt = ++p;
180231200Smm	}
181231200Smm
182231200Smm	p = strchr(opt, '=');
183231200Smm	if (p != NULL) {
184231200Smm		*p = '\0';
185231200Smm		val = ++p;
186231200Smm	} else if (opt[0] == '!') {
187231200Smm		++opt;
188231200Smm		val = NULL;
189231200Smm	}
190231200Smm
191231200Smm	*s = end;
192231200Smm	*m = mod;
193231200Smm	*o = opt;
194231200Smm	*v = val;
195231200Smm
196231200Smm	return end;
197231200Smm}
198231200Smm
199