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 90248616Smm if (r2 == ARCHIVE_WARN - 1) 91248616Smm return r1; 92231200Smm return r1 > r2 ? r1 : r2; 93231200Smm} 94231200Smm 95231200Smmint 96231200Smm_archive_set_options(struct archive *a, const char *options, 97231200Smm int magic, const char *fn, option_handler use_option) 98231200Smm{ 99248616Smm int allok = 1, anyok = 0, ignore_mod_err = 0, r; 100231200Smm char *data; 101231200Smm const char *s, *mod, *opt, *val; 102231200Smm 103231200Smm archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 104231200Smm 105231200Smm if (options == NULL || options[0] == '\0') 106231200Smm return ARCHIVE_OK; 107231200Smm 108231200Smm data = (char *)malloc(strlen(options) + 1); 109231200Smm strcpy(data, options); 110231200Smm s = (const char *)data; 111231200Smm 112231200Smm do { 113231200Smm mod = opt = val = NULL; 114231200Smm 115231200Smm parse_option(&s, &mod, &opt, &val); 116248616Smm if (mod == NULL && opt != NULL && 117248616Smm strcmp("__ignore_wrong_module_name__", opt) == 0) { 118248616Smm /* Ignore module name error */ 119248616Smm if (val != NULL) { 120248616Smm ignore_mod_err = 1; 121248616Smm anyok = 1; 122248616Smm } 123248616Smm continue; 124248616Smm } 125231200Smm 126231200Smm r = use_option(a, mod, opt, val); 127231200Smm if (r == ARCHIVE_FATAL) { 128231200Smm free(data); 129231200Smm return (ARCHIVE_FATAL); 130231200Smm } 131232153Smm if (r == ARCHIVE_FAILED && mod != NULL) { 132232153Smm free(data); 133232153Smm return (ARCHIVE_FAILED); 134232153Smm } 135232153Smm if (r == ARCHIVE_WARN - 1) { 136248616Smm if (ignore_mod_err) 137248616Smm continue; 138232153Smm /* The module name is wrong. */ 139232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 140232153Smm "Unknown module name: `%s'", mod); 141232153Smm free(data); 142232153Smm return (ARCHIVE_FAILED); 143232153Smm } 144232153Smm if (r == ARCHIVE_WARN) { 145232153Smm /* The option name is wrong. No-one used this. */ 146232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 147232153Smm "Undefined option: `%s%s%s'", 148232153Smm mod?mod:"", mod?":":"", opt); 149232153Smm free(data); 150232153Smm return (ARCHIVE_FAILED); 151232153Smm } 152231200Smm if (r == ARCHIVE_OK) 153231200Smm anyok = 1; 154231200Smm else 155231200Smm allok = 0; 156231200Smm } while (s != NULL); 157231200Smm 158231200Smm free(data); 159231200Smm return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; 160231200Smm} 161231200Smm 162231200Smmstatic const char * 163231200Smmparse_option(const char **s, const char **m, const char **o, const char **v) 164231200Smm{ 165231200Smm const char *end, *mod, *opt, *val; 166231200Smm char *p; 167231200Smm 168231200Smm end = NULL; 169231200Smm mod = NULL; 170231200Smm opt = *s; 171231200Smm val = "1"; 172231200Smm 173231200Smm p = strchr(opt, ','); 174231200Smm 175231200Smm if (p != NULL) { 176231200Smm *p = '\0'; 177231200Smm end = ((const char *)p) + 1; 178231200Smm } 179231200Smm 180231200Smm if (0 == strlen(opt)) { 181231200Smm *s = end; 182231200Smm *m = NULL; 183231200Smm *o = NULL; 184231200Smm *v = NULL; 185231200Smm return end; 186231200Smm } 187231200Smm 188231200Smm p = strchr(opt, ':'); 189231200Smm if (p != NULL) { 190231200Smm *p = '\0'; 191231200Smm mod = opt; 192231200Smm opt = ++p; 193231200Smm } 194231200Smm 195231200Smm p = strchr(opt, '='); 196231200Smm if (p != NULL) { 197231200Smm *p = '\0'; 198231200Smm val = ++p; 199231200Smm } else if (opt[0] == '!') { 200231200Smm ++opt; 201231200Smm val = NULL; 202231200Smm } 203231200Smm 204231200Smm *s = end; 205231200Smm *m = mod; 206231200Smm *o = opt; 207231200Smm *v = val; 208231200Smm 209231200Smm return end; 210231200Smm} 211231200Smm 212