1 /*- 2 * Copyright (c) 2011 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "archive_platform.h" 27 __FBSDID("$FreeBSD$"); 28 29 #include "archive_options_private.h" 30 31 static const char * 32 parse_option(const char **str, 33 const char **mod, const char **opt, const char **val); 34 35 int 36 _archive_set_option(struct archive *a, 37 const char *m, const char *o, const char *v, 38 int magic, const char *fn, option_handler use_option) 39 { 40 const char *mp, *op, *vp; 41 42 archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 43 44 mp = m != NULL && m[0] == '\0' ? NULL : m; 45 op = o != NULL && o[0] == '\0' ? NULL : o; 46 vp = v != NULL && v[0] == '\0' ? NULL : v; 47 48 if (op == NULL && vp == NULL) 49 return (ARCHIVE_OK); 50 if (op == NULL) 51 return (ARCHIVE_FAILED); 52 53 return use_option(a, mp, op, vp); 54 } 55 56 int 57 _archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v, 58 option_handler use_format_option, option_handler use_filter_option) 59 { 60 int r1, r2; 61 62 if (o == NULL && v == NULL) 63 return (ARCHIVE_OK); 64 if (o == NULL) 65 return (ARCHIVE_FAILED); 66 67 r1 = use_format_option(a, m, o, v); 68 if (r1 == ARCHIVE_FATAL) 69 return (ARCHIVE_FATAL); 70 71 r2 = use_filter_option(a, m, o, v); 72 if (r2 == ARCHIVE_FATAL) 73 return (ARCHIVE_FATAL); 74 75 return r1 > r2 ? r1 : r2; 76 } 77 78 int 79 _archive_set_options(struct archive *a, const char *options, 80 int magic, const char *fn, option_handler use_option) 81 { 82 int allok = 1, anyok = 0, r; 83 char *data; 84 const char *s, *mod, *opt, *val; 85 86 archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); 87 88 if (options == NULL || options[0] == '\0') 89 return ARCHIVE_OK; 90 91 data = (char *)malloc(strlen(options) + 1); 92 strcpy(data, options); 93 s = (const char *)data; 94 95 do { 96 mod = opt = val = NULL; 97 98 parse_option(&s, &mod, &opt, &val); 99 100 r = use_option(a, mod, opt, val); 101 if (r == ARCHIVE_FATAL) { 102 free(data); 103 return (ARCHIVE_FATAL); 104 } 105 if (r == ARCHIVE_OK) 106 anyok = 1; 107 else 108 allok = 0; 109 } while (s != NULL); 110 111 free(data); 112 return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; 113 } 114 115 static const char * 116 parse_option(const char **s, const char **m, const char **o, const char **v) 117 { 118 const char *end, *mod, *opt, *val; 119 char *p; 120 121 end = NULL; 122 mod = NULL; 123 opt = *s; 124 val = "1"; 125 126 p = strchr(opt, ','); 127 128 if (p != NULL) { 129 *p = '\0'; 130 end = ((const char *)p) + 1; 131 } 132 133 if (0 == strlen(opt)) { 134 *s = end; 135 *m = NULL; 136 *o = NULL; 137 *v = NULL; 138 return end; 139 } 140 141 p = strchr(opt, ':'); 142 if (p != NULL) { 143 *p = '\0'; 144 mod = opt; 145 opt = ++p; 146 } 147 148 p = strchr(opt, '='); 149 if (p != NULL) { 150 *p = '\0'; 151 val = ++p; 152 } else if (opt[0] == '!') { 153 ++opt; 154 val = NULL; 155 } 156 157 *s = end; 158 *m = mod; 159 *o = opt; 160 *v = val; 161 162 return end; 163 } 164 165