PageRenderTime 29ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/libarchive/tar/subst.c

https://gitlab.com/HowTheStoryEnds/freebsd11-psm-port
C | 326 lines | 255 code | 45 blank | 26 comment | 63 complexity | 14df9ae63c5fcf1f6832bac99a76828f MD5 | raw file
  1. /*-
  2. * Copyright (c) 2008 Joerg Sonnenberger
  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 "bsdtar_platform.h"
  26. __FBSDID("$FreeBSD: src/usr.bin/tar/subst.c,v 1.4 2008/06/15 10:08:16 kientzle Exp $");
  27. #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
  28. #include "bsdtar.h"
  29. #include <errno.h>
  30. #ifdef HAVE_PCREPOSIX_H
  31. #include <pcreposix.h>
  32. #else
  33. #include <regex.h>
  34. #endif
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #ifndef REG_BASIC
  38. #define REG_BASIC 0
  39. #endif
  40. #include "err.h"
  41. struct subst_rule {
  42. struct subst_rule *next;
  43. regex_t re;
  44. char *result;
  45. unsigned int global:1, print:1, regular:1, symlink:1, hardlink:1;
  46. };
  47. struct substitution {
  48. struct subst_rule *first_rule, *last_rule;
  49. };
  50. static void
  51. init_substitution(struct bsdtar *bsdtar)
  52. {
  53. struct substitution *subst;
  54. bsdtar->substitution = subst = malloc(sizeof(*subst));
  55. if (subst == NULL)
  56. lafe_errc(1, errno, "Out of memory");
  57. subst->first_rule = subst->last_rule = NULL;
  58. }
  59. void
  60. add_substitution(struct bsdtar *bsdtar, const char *rule_text)
  61. {
  62. struct subst_rule *rule;
  63. struct substitution *subst;
  64. const char *end_pattern, *start_subst;
  65. char *pattern;
  66. int r;
  67. if ((subst = bsdtar->substitution) == NULL) {
  68. init_substitution(bsdtar);
  69. subst = bsdtar->substitution;
  70. }
  71. rule = malloc(sizeof(*rule));
  72. if (rule == NULL)
  73. lafe_errc(1, errno, "Out of memory");
  74. rule->next = NULL;
  75. if (subst->last_rule == NULL)
  76. subst->first_rule = rule;
  77. else
  78. subst->last_rule->next = rule;
  79. subst->last_rule = rule;
  80. if (*rule_text == '\0')
  81. lafe_errc(1, 0, "Empty replacement string");
  82. end_pattern = strchr(rule_text + 1, *rule_text);
  83. if (end_pattern == NULL)
  84. lafe_errc(1, 0, "Invalid replacement string");
  85. pattern = malloc(end_pattern - rule_text);
  86. if (pattern == NULL)
  87. lafe_errc(1, errno, "Out of memory");
  88. memcpy(pattern, rule_text + 1, end_pattern - rule_text - 1);
  89. pattern[end_pattern - rule_text - 1] = '\0';
  90. if ((r = regcomp(&rule->re, pattern, REG_BASIC)) != 0) {
  91. char buf[80];
  92. regerror(r, &rule->re, buf, sizeof(buf));
  93. lafe_errc(1, 0, "Invalid regular expression: %s", buf);
  94. }
  95. free(pattern);
  96. start_subst = end_pattern + 1;
  97. end_pattern = strchr(start_subst, *rule_text);
  98. if (end_pattern == NULL)
  99. lafe_errc(1, 0, "Invalid replacement string");
  100. rule->result = malloc(end_pattern - start_subst + 1);
  101. if (rule->result == NULL)
  102. lafe_errc(1, errno, "Out of memory");
  103. memcpy(rule->result, start_subst, end_pattern - start_subst);
  104. rule->result[end_pattern - start_subst] = '\0';
  105. /* Defaults */
  106. rule->global = 0; /* Don't do multiple replacements. */
  107. rule->print = 0; /* Don't print. */
  108. rule->regular = 1; /* Rewrite regular filenames. */
  109. rule->symlink = 1; /* Rewrite symlink targets. */
  110. rule->hardlink = 1; /* Rewrite hardlink targets. */
  111. while (*++end_pattern) {
  112. switch (*end_pattern) {
  113. case 'g':
  114. case 'G':
  115. rule->global = 1;
  116. break;
  117. case 'h':
  118. rule->hardlink = 1;
  119. break;
  120. case 'H':
  121. rule->hardlink = 0;
  122. break;
  123. case 'p':
  124. case 'P':
  125. rule->print = 1;
  126. break;
  127. case 'r':
  128. rule->regular = 1;
  129. break;
  130. case 'R':
  131. rule->regular = 0;
  132. break;
  133. case 's':
  134. rule->symlink = 1;
  135. break;
  136. case 'S':
  137. rule->symlink = 0;
  138. break;
  139. default:
  140. lafe_errc(1, 0, "Invalid replacement flag %c", *end_pattern);
  141. }
  142. }
  143. }
  144. static void
  145. realloc_strncat(char **str, const char *append, size_t len)
  146. {
  147. char *new_str;
  148. size_t old_len;
  149. if (*str == NULL)
  150. old_len = 0;
  151. else
  152. old_len = strlen(*str);
  153. new_str = malloc(old_len + len + 1);
  154. if (new_str == NULL)
  155. lafe_errc(1, errno, "Out of memory");
  156. if (*str != NULL)
  157. memcpy(new_str, *str, old_len);
  158. memcpy(new_str + old_len, append, len);
  159. new_str[old_len + len] = '\0';
  160. free(*str);
  161. *str = new_str;
  162. }
  163. static void
  164. realloc_strcat(char **str, const char *append)
  165. {
  166. char *new_str;
  167. size_t old_len;
  168. if (*str == NULL)
  169. old_len = 0;
  170. else
  171. old_len = strlen(*str);
  172. new_str = malloc(old_len + strlen(append) + 1);
  173. if (new_str == NULL)
  174. lafe_errc(1, errno, "Out of memory");
  175. if (*str != NULL)
  176. memcpy(new_str, *str, old_len);
  177. strcpy(new_str + old_len, append);
  178. free(*str);
  179. *str = new_str;
  180. }
  181. int
  182. apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
  183. int symlink_target, int hardlink_target)
  184. {
  185. const char *path = name;
  186. regmatch_t matches[10];
  187. size_t i, j;
  188. struct subst_rule *rule;
  189. struct substitution *subst;
  190. int c, got_match, print_match;
  191. *result = NULL;
  192. if ((subst = bsdtar->substitution) == NULL)
  193. return 0;
  194. got_match = 0;
  195. print_match = 0;
  196. for (rule = subst->first_rule; rule != NULL; rule = rule->next) {
  197. if (symlink_target) {
  198. if (!rule->symlink)
  199. continue;
  200. } else if (hardlink_target) {
  201. if (!rule->hardlink)
  202. continue;
  203. } else { /* Regular filename. */
  204. if (!rule->regular)
  205. continue;
  206. }
  207. while (1) {
  208. if (regexec(&rule->re, name, 10, matches, 0))
  209. break;
  210. got_match = 1;
  211. print_match |= rule->print;
  212. realloc_strncat(result, name, matches[0].rm_so);
  213. for (i = 0, j = 0; rule->result[i] != '\0'; ++i) {
  214. if (rule->result[i] == '~') {
  215. realloc_strncat(result, rule->result + j, i - j);
  216. realloc_strncat(result,
  217. name + matches[0].rm_so,
  218. matches[0].rm_eo - matches[0].rm_so);
  219. j = i + 1;
  220. continue;
  221. }
  222. if (rule->result[i] != '\\')
  223. continue;
  224. ++i;
  225. c = rule->result[i];
  226. switch (c) {
  227. case '~':
  228. case '\\':
  229. realloc_strncat(result, rule->result + j, i - j - 1);
  230. j = i;
  231. break;
  232. case '1':
  233. case '2':
  234. case '3':
  235. case '4':
  236. case '5':
  237. case '6':
  238. case '7':
  239. case '8':
  240. case '9':
  241. realloc_strncat(result, rule->result + j, i - j - 1);
  242. if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
  243. free(*result);
  244. *result = NULL;
  245. return -1;
  246. }
  247. realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
  248. j = i + 1;
  249. break;
  250. default:
  251. /* Just continue; */
  252. break;
  253. }
  254. }
  255. realloc_strcat(result, rule->result + j);
  256. name += matches[0].rm_eo;
  257. if (!rule->global)
  258. break;
  259. }
  260. }
  261. if (got_match)
  262. realloc_strcat(result, name);
  263. if (print_match)
  264. fprintf(stderr, "%s >> %s\n", path, *result);
  265. return got_match;
  266. }
  267. void
  268. cleanup_substitution(struct bsdtar *bsdtar)
  269. {
  270. struct subst_rule *rule;
  271. struct substitution *subst;
  272. if ((subst = bsdtar->substitution) == NULL)
  273. return;
  274. while ((rule = subst->first_rule) != NULL) {
  275. subst->first_rule = rule->next;
  276. free(rule->result);
  277. free(rule);
  278. }
  279. free(subst);
  280. }
  281. #endif /* defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H) */