archive_options.c revision 311042
1142425Snectar/*- 2142425Snectar * Copyright (c) 2011 Tim Kientzle 3142425Snectar * All rights reserved. 4142425Snectar * 5142425Snectar * Redistribution and use in source and binary forms, with or without 6142425Snectar * modification, are permitted provided that the following conditions 7142425Snectar * are met: 8142425Snectar * 1. Redistributions of source code must retain the above copyright 9142425Snectar * notice, this list of conditions and the following disclaimer. 10142425Snectar * 2. Redistributions in binary form must reproduce the above copyright 11142425Snectar * notice, this list of conditions and the following disclaimer in the 12142425Snectar * documentation and/or other materials provided with the distribution. 13142425Snectar * 14142425Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15142425Snectar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16142425Snectar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17142425Snectar * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18142425Snectar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19142425Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20142425Snectar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21142425Snectar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22160814Ssimon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23160814Ssimon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24160814Ssimon */ 25142425Snectar 26142425Snectar#include "archive_platform.h" 27160814Ssimon__FBSDID("$FreeBSD$"); 28160814Ssimon 29160814Ssimon#ifdef HAVE_ERRNO_H 30142425Snectar#include <errno.h> 31142425Snectar#endif 32142425Snectar 33142425Snectar#include "archive_options_private.h" 34142425Snectar 35142425Snectarstatic const char * 36142425Snectarparse_option(const char **str, 37142425Snectar const char **mod, const char **opt, const char **val); 38142425Snectar 39142425Snectarint 40142425Snectar_archive_set_option(struct archive *a, 41142425Snectar const char *m, const char *o, const char *v, 42142425Snectar int magic, const char *fn, option_handler use_option) 43142425Snectar{ 44194206Ssimon const char *mp, *op, *vp; 45142425Snectar int r; 46142425Snectar 47142425Snectar archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 48142425Snectar 49142425Snectar mp = (m != NULL && m[0] != '\0') ? m : NULL; 50142425Snectar op = (o != NULL && o[0] != '\0') ? o : NULL; 51142425Snectar vp = (v != NULL && v[0] != '\0') ? v : NULL; 52142425Snectar 53142425Snectar if (op == NULL && vp == NULL) 54142425Snectar return (ARCHIVE_OK); 55142425Snectar if (op == NULL) { 56142425Snectar archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option"); 57160814Ssimon return (ARCHIVE_FAILED); 58160814Ssimon } 59142425Snectar 60142425Snectar r = use_option(a, mp, op, vp); 61142425Snectar if (r == ARCHIVE_WARN - 1) { 62142425Snectar archive_set_error(a, ARCHIVE_ERRNO_MISC, 63142425Snectar "Unknown module name: `%s'", mp); 64142425Snectar return (ARCHIVE_FAILED); 65142425Snectar } 66142425Snectar if (r == ARCHIVE_WARN) { 67142425Snectar archive_set_error(a, ARCHIVE_ERRNO_MISC, 68142425Snectar "Undefined option: `%s%s%s%s%s%s'", 69142425Snectar vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:""); 70142425Snectar return (ARCHIVE_FAILED); 71142425Snectar } 72142425Snectar return (r); 73160814Ssimon} 74142425Snectar 75142425Snectarint 76142425Snectar_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v, 77142425Snectar option_handler use_format_option, option_handler use_filter_option) 78142425Snectar{ 79142425Snectar int r1, r2; 80142425Snectar 81142425Snectar if (o == NULL && v == NULL) 82142425Snectar return (ARCHIVE_OK); 83142425Snectar if (o == NULL) 84142425Snectar return (ARCHIVE_FAILED); 85194206Ssimon 86194206Ssimon r1 = use_format_option(a, m, o, v); 87194206Ssimon if (r1 == ARCHIVE_FATAL) 88194206Ssimon return (ARCHIVE_FATAL); 89194206Ssimon 90194206Ssimon r2 = use_filter_option(a, m, o, v); 91194206Ssimon if (r2 == ARCHIVE_FATAL) 92194206Ssimon return (ARCHIVE_FATAL); 93142425Snectar 94194206Ssimon if (r2 == ARCHIVE_WARN - 1) 95194206Ssimon return r1; 96142425Snectar return r1 > r2 ? r1 : r2; 97194206Ssimon} 98160814Ssimon 99194206Ssimonint 100194206Ssimon_archive_set_options(struct archive *a, const char *options, 101194206Ssimon int magic, const char *fn, option_handler use_option) 102194206Ssimon{ 103194206Ssimon int allok = 1, anyok = 0, ignore_mod_err = 0, r; 104142425Snectar char *data; 105194206Ssimon const char *s, *mod, *opt, *val; 106194206Ssimon 107194206Ssimon archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 108142425Snectar 109194206Ssimon if (options == NULL || options[0] == '\0') 110194206Ssimon return ARCHIVE_OK; 111194206Ssimon 112194206Ssimon if ((data = strdup(options)) == NULL) { 113160814Ssimon archive_set_error(a, 114194206Ssimon ENOMEM, "Out of memory adding file to list"); 115205128Ssimon return (ARCHIVE_FATAL); 116205128Ssimon } 117194206Ssimon s = (const char *)data; 118194206Ssimon 119205128Ssimon do { 120205128Ssimon mod = opt = val = NULL; 121205128Ssimon 122160814Ssimon parse_option(&s, &mod, &opt, &val); 123160814Ssimon if (mod == NULL && opt != NULL && 124160814Ssimon strcmp("__ignore_wrong_module_name__", opt) == 0) { 125194206Ssimon /* Ignore module name error */ 126205128Ssimon if (val != NULL) { 127205128Ssimon ignore_mod_err = 1; 128205128Ssimon anyok = 1; 129205128Ssimon } 130194206Ssimon continue; 131194206Ssimon } 132194206Ssimon 133194206Ssimon r = use_option(a, mod, opt, val); 134194206Ssimon if (r == ARCHIVE_FATAL) { 135194206Ssimon free(data); 136194206Ssimon return (ARCHIVE_FATAL); 137194206Ssimon } 138142425Snectar if (r == ARCHIVE_FAILED && mod != NULL) { 139142425Snectar free(data); 140194206Ssimon return (ARCHIVE_FAILED); 141194206Ssimon } 142194206Ssimon if (r == ARCHIVE_WARN - 1) { 143194206Ssimon if (ignore_mod_err) 144194206Ssimon continue; 145194206Ssimon /* The module name is wrong. */ 146194206Ssimon archive_set_error(a, ARCHIVE_ERRNO_MISC, 147194206Ssimon "Unknown module name: `%s'", mod); 148194206Ssimon free(data); 149142425Snectar return (ARCHIVE_FAILED); 150194206Ssimon } 151194206Ssimon if (r == ARCHIVE_WARN) { 152194206Ssimon /* The option name is wrong. No-one used this. */ 153142425Snectar archive_set_error(a, ARCHIVE_ERRNO_MISC, 154194206Ssimon "Undefined option: `%s%s%s'", 155194206Ssimon mod?mod:"", mod?":":"", opt); 156194206Ssimon free(data); 157194206Ssimon return (ARCHIVE_FAILED); 158194206Ssimon } 159194206Ssimon if (r == ARCHIVE_OK) 160194206Ssimon anyok = 1; 161194206Ssimon else 162194206Ssimon allok = 0; 163194206Ssimon } while (s != NULL); 164194206Ssimon 165194206Ssimon free(data); 166194206Ssimon return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; 167194206Ssimon} 168194206Ssimon 169194206Ssimonstatic const char * 170194206Ssimonparse_option(const char **s, const char **m, const char **o, const char **v) 171194206Ssimon{ 172194206Ssimon const char *end, *mod, *opt, *val; 173194206Ssimon char *p; 174194206Ssimon 175194206Ssimon end = NULL; 176142425Snectar mod = NULL; 177194206Ssimon opt = *s; 178194206Ssimon val = "1"; 179194206Ssimon 180142425Snectar p = strchr(opt, ','); 181194206Ssimon 182194206Ssimon if (p != NULL) { 183194206Ssimon *p = '\0'; 184194206Ssimon end = ((const char *)p) + 1; 185194206Ssimon } 186194206Ssimon 187194206Ssimon if (0 == strlen(opt)) { 188194206Ssimon *s = end; 189194206Ssimon *m = NULL; 190194206Ssimon *o = NULL; 191194206Ssimon *v = NULL; 192194206Ssimon return end; 193142425Snectar } 194142425Snectar 195194206Ssimon p = strchr(opt, ':'); 196194206Ssimon if (p != NULL) { 197194206Ssimon *p = '\0'; 198194206Ssimon mod = opt; 199194206Ssimon opt = ++p; 200194206Ssimon } 201194206Ssimon 202194206Ssimon p = strchr(opt, '='); 203194206Ssimon if (p != NULL) { 204194206Ssimon *p = '\0'; 205194206Ssimon val = ++p; 206194206Ssimon } else if (opt[0] == '!') { 207142425Snectar ++opt; 208194206Ssimon val = NULL; 209194206Ssimon } 210194206Ssimon 211194206Ssimon *s = end; 212194206Ssimon *m = mod; 213194206Ssimon *o = opt; 214194206Ssimon *v = val; 215194206Ssimon 216194206Ssimon return end; 217194206Ssimon} 218194206Ssimon 219194206Ssimon