archive_options.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. #include "archive_platform.h"
  26. __FBSDID("$FreeBSD$");
  27. #ifdef HAVE_ERRNO_H
  28. #include <errno.h>
  29. #endif
  30. #include "archive_options_private.h"
  31. static const char *
  32. parse_option(const char **str,
  33. const char **mod, const char **opt, const char **val);
  34. int
  35. _archive_set_option(struct archive *a,
  36. const char *m, const char *o, const char *v,
  37. int magic, const char *fn, option_handler use_option)
  38. {
  39. const char *mp, *op, *vp;
  40. int r;
  41. archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
  42. mp = (m != NULL && m[0] != '\0') ? m : NULL;
  43. op = (o != NULL && o[0] != '\0') ? o : NULL;
  44. vp = (v != NULL && v[0] != '\0') ? v : NULL;
  45. if (op == NULL && vp == NULL)
  46. return (ARCHIVE_OK);
  47. if (op == NULL) {
  48. archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
  49. return (ARCHIVE_FAILED);
  50. }
  51. r = use_option(a, mp, op, vp);
  52. if (r == ARCHIVE_WARN - 1) {
  53. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  54. "Unknown module name: `%s'", mp);
  55. return (ARCHIVE_FAILED);
  56. }
  57. if (r == ARCHIVE_WARN) {
  58. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  59. "Undefined option: `%s%s%s%s%s%s'",
  60. vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
  61. return (ARCHIVE_FAILED);
  62. }
  63. return (r);
  64. }
  65. int
  66. _archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v,
  67. option_handler use_format_option, option_handler use_filter_option)
  68. {
  69. int r1, r2;
  70. if (o == NULL && v == NULL)
  71. return (ARCHIVE_OK);
  72. if (o == NULL)
  73. return (ARCHIVE_FAILED);
  74. r1 = use_format_option(a, m, o, v);
  75. if (r1 == ARCHIVE_FATAL)
  76. return (ARCHIVE_FATAL);
  77. r2 = use_filter_option(a, m, o, v);
  78. if (r2 == ARCHIVE_FATAL)
  79. return (ARCHIVE_FATAL);
  80. if (r2 == ARCHIVE_WARN - 1)
  81. return r1;
  82. return r1 > r2 ? r1 : r2;
  83. }
  84. int
  85. _archive_set_options(struct archive *a, const char *options,
  86. int magic, const char *fn, option_handler use_option)
  87. {
  88. int allok = 1, anyok = 0, ignore_mod_err = 0, r;
  89. char *data;
  90. const char *s, *mod, *opt, *val;
  91. archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
  92. if (options == NULL || options[0] == '\0')
  93. return ARCHIVE_OK;
  94. if ((data = strdup(options)) == NULL) {
  95. archive_set_error(a,
  96. ENOMEM, "Out of memory adding file to list");
  97. return (ARCHIVE_FATAL);
  98. }
  99. s = (const char *)data;
  100. do {
  101. mod = opt = val = NULL;
  102. parse_option(&s, &mod, &opt, &val);
  103. if (mod == NULL && opt != NULL &&
  104. strcmp("__ignore_wrong_module_name__", opt) == 0) {
  105. /* Ignore module name error */
  106. if (val != NULL) {
  107. ignore_mod_err = 1;
  108. anyok = 1;
  109. }
  110. continue;
  111. }
  112. r = use_option(a, mod, opt, val);
  113. if (r == ARCHIVE_FATAL) {
  114. free(data);
  115. return (ARCHIVE_FATAL);
  116. }
  117. if (r == ARCHIVE_FAILED && mod != NULL) {
  118. free(data);
  119. return (ARCHIVE_FAILED);
  120. }
  121. if (r == ARCHIVE_WARN - 1) {
  122. if (ignore_mod_err)
  123. continue;
  124. /* The module name is wrong. */
  125. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  126. "Unknown module name: `%s'", mod);
  127. free(data);
  128. return (ARCHIVE_FAILED);
  129. }
  130. if (r == ARCHIVE_WARN) {
  131. /* The option name is wrong. No-one used this. */
  132. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  133. "Undefined option: `%s%s%s'",
  134. mod?mod:"", mod?":":"", opt);
  135. free(data);
  136. return (ARCHIVE_FAILED);
  137. }
  138. if (r == ARCHIVE_OK)
  139. anyok = 1;
  140. else
  141. allok = 0;
  142. } while (s != NULL);
  143. free(data);
  144. return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED;
  145. }
  146. static const char *
  147. parse_option(const char **s, const char **m, const char **o, const char **v)
  148. {
  149. const char *end, *mod, *opt, *val;
  150. char *p;
  151. end = NULL;
  152. mod = NULL;
  153. opt = *s;
  154. val = "1";
  155. p = strchr(opt, ',');
  156. if (p != NULL) {
  157. *p = '\0';
  158. end = ((const char *)p) + 1;
  159. }
  160. if (0 == strlen(opt)) {
  161. *s = end;
  162. *m = NULL;
  163. *o = NULL;
  164. *v = NULL;
  165. return end;
  166. }
  167. p = strchr(opt, ':');
  168. if (p != NULL) {
  169. *p = '\0';
  170. mod = opt;
  171. opt = ++p;
  172. }
  173. p = strchr(opt, '=');
  174. if (p != NULL) {
  175. *p = '\0';
  176. val = ++p;
  177. } else if (opt[0] == '!') {
  178. ++opt;
  179. val = NULL;
  180. }
  181. *s = end;
  182. *m = mod;
  183. *o = opt;
  184. *v = val;
  185. return end;
  186. }