filters.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * dpkg - main program for package management
  3. * filters.c - filtering routines for excluding bits of packages
  4. *
  5. * Copyright © 2007, 2008 Tollef Fog Heen <tfheen@err.no>
  6. * Copyright © 2008, 2010, 2012-2014 Guillem Jover <guillem@debian.org>
  7. * Copyright © 2010 Canonical Ltd.
  8. * written by Martin Pitt <martin.pitt@canonical.com>
  9. *
  10. * This is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  22. */
  23. #include <config.h>
  24. #include <compat.h>
  25. #include <fnmatch.h>
  26. #include <dpkg/i18n.h>
  27. #include <dpkg/dpkg.h>
  28. #include <dpkg/dpkg-db.h>
  29. #include "main.h"
  30. #include "filesdb.h"
  31. #include "filters.h"
  32. struct filter_node {
  33. struct filter_node *next;
  34. char *pattern;
  35. bool include;
  36. };
  37. static struct filter_node *filter_head = NULL;
  38. static struct filter_node **filter_tail = &filter_head;
  39. void
  40. filter_add(const char *pattern, bool include)
  41. {
  42. struct filter_node *filter;
  43. debug(dbg_general, "adding %s filter for '%s'",
  44. include ? "include" : "exclude", pattern);
  45. filter = m_malloc(sizeof(*filter));
  46. filter->pattern = m_strdup(pattern);
  47. filter->include = include;
  48. filter->next = NULL;
  49. *filter_tail = filter;
  50. filter_tail = &filter->next;
  51. }
  52. bool
  53. filter_should_skip(struct tar_entry *ti)
  54. {
  55. struct filter_node *f;
  56. bool skip = false;
  57. if (!filter_head)
  58. return false;
  59. /* Last match wins. */
  60. for (f = filter_head; f != NULL; f = f->next) {
  61. debug(dbg_eachfile, "filter comparing '%s' and '%s'",
  62. &ti->name[1], f->pattern);
  63. if (fnmatch(f->pattern, &ti->name[1], 0) == 0) {
  64. if (f->include) {
  65. skip = false;
  66. debug(dbg_eachfile, "filter including %s",
  67. ti->name);
  68. } else {
  69. skip = true;
  70. debug(dbg_eachfile, "filter removing %s",
  71. ti->name);
  72. }
  73. }
  74. }
  75. /* We need to keep directories (or symlinks to directories) if a
  76. * glob excludes them, but a more specific include glob brings back
  77. * files; XXX the current implementation will probably include more
  78. * directories than necessary, but better err on the side of caution
  79. * than failing with “no such file or directory” (which would leave
  80. * the package in a very bad state). */
  81. if (skip && (ti->type == TAR_FILETYPE_DIR ||
  82. ti->type == TAR_FILETYPE_SYMLINK)) {
  83. debug(dbg_eachfile,
  84. "filter seeing if '%s' needs to be reincluded",
  85. &ti->name[1]);
  86. for (f = filter_head; f != NULL; f = f->next) {
  87. const char *wildcard;
  88. int path_len;
  89. if (!f->include)
  90. continue;
  91. /* Calculate the offset of the first wildcard
  92. * character in the pattern. */
  93. wildcard = strpbrk(f->pattern, "*?[\\");
  94. if (wildcard)
  95. path_len = wildcard - f->pattern;
  96. else
  97. path_len = strlen(f->pattern);
  98. /* Ignore any trailing slash for the comparison. */
  99. while (path_len && f->pattern[path_len - 1] == '/')
  100. path_len--;
  101. debug(dbg_eachfiledetail,
  102. "filter subpattern '%.*s'", path_len, f->pattern);
  103. if (strncmp(&ti->name[1], f->pattern, path_len) == 0) {
  104. debug(dbg_eachfile, "filter reincluding %s",
  105. ti->name);
  106. return false;
  107. }
  108. }
  109. }
  110. return skip;
  111. }