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 29311042Smm#ifdef HAVE_ERRNO_H 30311042Smm#include <errno.h> 31311042Smm#endif 32311042Smm 33231200Smm#include "archive_options_private.h" 34231200Smm 35231200Smmstatic const char * 36231200Smmparse_option(const char **str, 37231200Smm const char **mod, const char **opt, const char **val); 38231200Smm 39231200Smmint 40231200Smm_archive_set_option(struct archive *a, 41231200Smm const char *m, const char *o, const char *v, 42231200Smm int magic, const char *fn, option_handler use_option) 43231200Smm{ 44231200Smm const char *mp, *op, *vp; 45232153Smm int r; 46231200Smm 47231200Smm archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 48231200Smm 49302001Smm mp = (m != NULL && m[0] != '\0') ? m : NULL; 50302001Smm op = (o != NULL && o[0] != '\0') ? o : NULL; 51302001Smm vp = (v != NULL && v[0] != '\0') ? v : NULL; 52231200Smm 53231200Smm if (op == NULL && vp == NULL) 54231200Smm return (ARCHIVE_OK); 55232153Smm if (op == NULL) { 56232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option"); 57231200Smm return (ARCHIVE_FAILED); 58232153Smm } 59231200Smm 60232153Smm r = use_option(a, mp, op, vp); 61232153Smm if (r == ARCHIVE_WARN - 1) { 62232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 63232153Smm "Unknown module name: `%s'", mp); 64232153Smm return (ARCHIVE_FAILED); 65232153Smm } 66232153Smm if (r == ARCHIVE_WARN) { 67232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 68232153Smm "Undefined option: `%s%s%s%s%s%s'", 69232153Smm vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:""); 70232153Smm return (ARCHIVE_FAILED); 71232153Smm } 72232153Smm return (r); 73231200Smm} 74231200Smm 75231200Smmint 76231200Smm_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v, 77231200Smm option_handler use_format_option, option_handler use_filter_option) 78231200Smm{ 79231200Smm int r1, r2; 80231200Smm 81231200Smm if (o == NULL && v == NULL) 82231200Smm return (ARCHIVE_OK); 83231200Smm if (o == NULL) 84231200Smm return (ARCHIVE_FAILED); 85231200Smm 86231200Smm r1 = use_format_option(a, m, o, v); 87231200Smm if (r1 == ARCHIVE_FATAL) 88231200Smm return (ARCHIVE_FATAL); 89231200Smm 90231200Smm r2 = use_filter_option(a, m, o, v); 91231200Smm if (r2 == ARCHIVE_FATAL) 92231200Smm return (ARCHIVE_FATAL); 93231200Smm 94248616Smm if (r2 == ARCHIVE_WARN - 1) 95248616Smm return r1; 96231200Smm return r1 > r2 ? r1 : r2; 97231200Smm} 98231200Smm 99231200Smmint 100231200Smm_archive_set_options(struct archive *a, const char *options, 101231200Smm int magic, const char *fn, option_handler use_option) 102231200Smm{ 103248616Smm int allok = 1, anyok = 0, ignore_mod_err = 0, r; 104231200Smm char *data; 105231200Smm const char *s, *mod, *opt, *val; 106231200Smm 107231200Smm archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 108231200Smm 109231200Smm if (options == NULL || options[0] == '\0') 110231200Smm return ARCHIVE_OK; 111231200Smm 112311042Smm if ((data = strdup(options)) == NULL) { 113311042Smm archive_set_error(a, 114311042Smm ENOMEM, "Out of memory adding file to list"); 115311042Smm return (ARCHIVE_FATAL); 116311042Smm } 117231200Smm s = (const char *)data; 118231200Smm 119231200Smm do { 120231200Smm mod = opt = val = NULL; 121231200Smm 122231200Smm parse_option(&s, &mod, &opt, &val); 123248616Smm if (mod == NULL && opt != NULL && 124248616Smm strcmp("__ignore_wrong_module_name__", opt) == 0) { 125248616Smm /* Ignore module name error */ 126248616Smm if (val != NULL) { 127248616Smm ignore_mod_err = 1; 128248616Smm anyok = 1; 129248616Smm } 130248616Smm continue; 131248616Smm } 132231200Smm 133231200Smm r = use_option(a, mod, opt, val); 134231200Smm if (r == ARCHIVE_FATAL) { 135231200Smm free(data); 136231200Smm return (ARCHIVE_FATAL); 137231200Smm } 138232153Smm if (r == ARCHIVE_FAILED && mod != NULL) { 139232153Smm free(data); 140232153Smm return (ARCHIVE_FAILED); 141232153Smm } 142232153Smm if (r == ARCHIVE_WARN - 1) { 143248616Smm if (ignore_mod_err) 144248616Smm continue; 145232153Smm /* The module name is wrong. */ 146232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 147232153Smm "Unknown module name: `%s'", mod); 148232153Smm free(data); 149232153Smm return (ARCHIVE_FAILED); 150232153Smm } 151232153Smm if (r == ARCHIVE_WARN) { 152232153Smm /* The option name is wrong. No-one used this. */ 153232153Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 154232153Smm "Undefined option: `%s%s%s'", 155232153Smm mod?mod:"", mod?":":"", opt); 156232153Smm free(data); 157232153Smm return (ARCHIVE_FAILED); 158232153Smm } 159231200Smm if (r == ARCHIVE_OK) 160231200Smm anyok = 1; 161231200Smm else 162231200Smm allok = 0; 163231200Smm } while (s != NULL); 164231200Smm 165231200Smm free(data); 166231200Smm return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; 167231200Smm} 168231200Smm 169231200Smmstatic const char * 170231200Smmparse_option(const char **s, const char **m, const char **o, const char **v) 171231200Smm{ 172231200Smm const char *end, *mod, *opt, *val; 173231200Smm char *p; 174231200Smm 175231200Smm end = NULL; 176231200Smm mod = NULL; 177231200Smm opt = *s; 178231200Smm val = "1"; 179231200Smm 180231200Smm p = strchr(opt, ','); 181231200Smm 182231200Smm if (p != NULL) { 183231200Smm *p = '\0'; 184231200Smm end = ((const char *)p) + 1; 185231200Smm } 186231200Smm 187231200Smm if (0 == strlen(opt)) { 188231200Smm *s = end; 189231200Smm *m = NULL; 190231200Smm *o = NULL; 191231200Smm *v = NULL; 192231200Smm return end; 193231200Smm } 194231200Smm 195231200Smm p = strchr(opt, ':'); 196231200Smm if (p != NULL) { 197231200Smm *p = '\0'; 198231200Smm mod = opt; 199231200Smm opt = ++p; 200231200Smm } 201231200Smm 202231200Smm p = strchr(opt, '='); 203231200Smm if (p != NULL) { 204231200Smm *p = '\0'; 205231200Smm val = ++p; 206231200Smm } else if (opt[0] == '!') { 207231200Smm ++opt; 208231200Smm val = NULL; 209231200Smm } 210231200Smm 211231200Smm *s = end; 212231200Smm *m = mod; 213231200Smm *o = opt; 214231200Smm *v = val; 215231200Smm 216231200Smm return end; 217231200Smm} 218231200Smm 219