pkg-spec.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * pkg-spec.c - primitives for pkg specifier handling
  4. *
  5. * Copyright © 2011 Linaro Limited
  6. * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
  7. * Copyright © 2011-2015 Guillem Jover <guillem@debian.org>
  8. *
  9. * This is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  21. */
  22. #include <config.h>
  23. #include <compat.h>
  24. #include <stdlib.h>
  25. #include <fnmatch.h>
  26. #include <string.h>
  27. #include <dpkg/i18n.h>
  28. #include <dpkg/dpkg.h>
  29. #include <dpkg/dpkg-db.h>
  30. #include <dpkg/arch.h>
  31. #include <dpkg/pkg-spec.h>
  32. static void
  33. pkg_spec_blank(struct pkg_spec *ps)
  34. {
  35. ps->name = NULL;
  36. ps->arch = NULL;
  37. ps->name_is_pattern = false;
  38. ps->arch_is_pattern = false;
  39. }
  40. static void
  41. pkg_spec_iter_blank(struct pkg_spec *ps)
  42. {
  43. ps->pkg_iter = NULL;
  44. ps->pkg_next = NULL;
  45. }
  46. void
  47. pkg_spec_init(struct pkg_spec *ps, enum pkg_spec_flags flags)
  48. {
  49. ps->flags = flags;
  50. pkg_spec_blank(ps);
  51. pkg_spec_iter_blank(ps);
  52. }
  53. const char *
  54. pkg_spec_is_illegal(struct pkg_spec *ps)
  55. {
  56. static char msg[1024];
  57. const char *emsg;
  58. if (!ps->name_is_pattern &&
  59. (emsg = pkg_name_is_illegal(ps->name))) {
  60. const char *arch_sep;
  61. /* Only check for DPKG_ARCH_NONE, because for everything else
  62. * we want to see the passed package specification, even if
  63. * the architecture is empty. */
  64. if (ps->arch->type == DPKG_ARCH_NONE)
  65. arch_sep = "";
  66. else
  67. arch_sep = ":";
  68. snprintf(msg, sizeof(msg),
  69. _("illegal package name in specifier '%s%s%s': %s"),
  70. ps->name, arch_sep, ps->arch->name, emsg);
  71. return msg;
  72. }
  73. if ((!ps->arch_is_pattern && ps->arch->type == DPKG_ARCH_ILLEGAL) ||
  74. ps->arch->type == DPKG_ARCH_EMPTY) {
  75. emsg = dpkg_arch_name_is_illegal(ps->arch->name);
  76. snprintf(msg, sizeof(msg),
  77. _("illegal architecture name in specifier '%s:%s': %s"),
  78. ps->name, ps->arch->name, emsg);
  79. return msg;
  80. }
  81. /* If we have been requested a single instance, check that the
  82. * package does not contain other instances. */
  83. if (!ps->arch_is_pattern && ps->flags & PKG_SPEC_ARCH_SINGLE) {
  84. struct pkgset *set;
  85. set = pkg_db_find_set(ps->name);
  86. /* Single instancing only applies with no architecture. */
  87. if (ps->arch->type == DPKG_ARCH_NONE &&
  88. pkgset_installed_instances(set) > 1) {
  89. snprintf(msg, sizeof(msg),
  90. _("ambiguous package name '%s' with more "
  91. "than one installed instance"), ps->name);
  92. return msg;
  93. }
  94. }
  95. return NULL;
  96. }
  97. static const char *
  98. pkg_spec_prep(struct pkg_spec *ps, char *pkgname, const char *archname)
  99. {
  100. ps->name = pkgname;
  101. ps->arch = dpkg_arch_find(archname);
  102. ps->name_is_pattern = false;
  103. ps->arch_is_pattern = false;
  104. /* Detect if we have patterns and/or illegal names. */
  105. if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->name, "*[?\\"))
  106. ps->name_is_pattern = true;
  107. if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->arch->name, "*[?\\"))
  108. ps->arch_is_pattern = true;
  109. return pkg_spec_is_illegal(ps);
  110. }
  111. const char *
  112. pkg_spec_set(struct pkg_spec *ps, const char *pkgname, const char *archname)
  113. {
  114. return pkg_spec_prep(ps, m_strdup(pkgname), archname);
  115. }
  116. const char *
  117. pkg_spec_parse(struct pkg_spec *ps, const char *str)
  118. {
  119. char *pkgname, *archname;
  120. archname = strchr(str, ':');
  121. if (archname == NULL) {
  122. pkgname = m_strdup(str);
  123. } else {
  124. pkgname = m_strndup(str, archname - str);
  125. archname++;
  126. }
  127. return pkg_spec_prep(ps, pkgname, archname);
  128. }
  129. static bool
  130. pkg_spec_match_name(struct pkg_spec *ps, const char *name)
  131. {
  132. if (ps->name_is_pattern)
  133. return (fnmatch(ps->name, name, 0) == 0);
  134. else
  135. return (strcmp(ps->name, name) == 0);
  136. }
  137. static bool
  138. pkg_spec_match_arch(struct pkg_spec *ps, struct pkginfo *pkg,
  139. const struct dpkg_arch *arch)
  140. {
  141. if (ps->arch_is_pattern)
  142. return (fnmatch(ps->arch->name, arch->name, 0) == 0);
  143. else if (ps->arch->type != DPKG_ARCH_NONE) /* !arch_is_pattern */
  144. return (ps->arch == arch);
  145. /* No arch specified. */
  146. switch (ps->flags & PKG_SPEC_ARCH_MASK) {
  147. case PKG_SPEC_ARCH_SINGLE:
  148. return pkgset_installed_instances(pkg->set) <= 1;
  149. case PKG_SPEC_ARCH_WILDCARD:
  150. return true;
  151. default:
  152. internerr("unknown PKG_SPEC_ARCH_* flags %d in pkg_spec",
  153. ps->flags & PKG_SPEC_ARCH_MASK);
  154. }
  155. }
  156. bool
  157. pkg_spec_match_pkg(struct pkg_spec *ps, struct pkginfo *pkg,
  158. struct pkgbin *pkgbin)
  159. {
  160. return (pkg_spec_match_name(ps, pkg->set->name) &&
  161. pkg_spec_match_arch(ps, pkg, pkgbin->arch));
  162. }
  163. static struct pkginfo *
  164. pkg_spec_get_pkg(struct pkg_spec *ps)
  165. {
  166. if (ps->arch->type == DPKG_ARCH_NONE)
  167. return pkg_db_find_singleton(ps->name);
  168. else
  169. return pkg_db_find_pkg(ps->name, ps->arch);
  170. }
  171. struct pkginfo *
  172. pkg_spec_parse_pkg(const char *str, struct dpkg_error *err)
  173. {
  174. struct pkg_spec ps;
  175. struct pkginfo *pkg;
  176. const char *emsg;
  177. pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
  178. emsg = pkg_spec_parse(&ps, str);
  179. if (emsg) {
  180. dpkg_put_error(err, "%s", emsg);
  181. pkg = NULL;
  182. } else {
  183. pkg = pkg_spec_get_pkg(&ps);
  184. }
  185. pkg_spec_destroy(&ps);
  186. return pkg;
  187. }
  188. struct pkginfo *
  189. pkg_spec_find_pkg(const char *pkgname, const char *archname,
  190. struct dpkg_error *err)
  191. {
  192. struct pkg_spec ps;
  193. struct pkginfo *pkg;
  194. const char *emsg;
  195. pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
  196. emsg = pkg_spec_set(&ps, pkgname, archname);
  197. if (emsg) {
  198. dpkg_put_error(err, "%s", emsg);
  199. pkg = NULL;
  200. } else {
  201. pkg = pkg_spec_get_pkg(&ps);
  202. }
  203. pkg_spec_destroy(&ps);
  204. return pkg;
  205. }
  206. void
  207. pkg_spec_iter_init(struct pkg_spec *ps)
  208. {
  209. if (ps->name_is_pattern)
  210. ps->pkg_iter = pkg_db_iter_new();
  211. else
  212. ps->pkg_next = &pkg_db_find_set(ps->name)->pkg;
  213. }
  214. static struct pkginfo *
  215. pkg_spec_iter_next_pkgname(struct pkg_spec *ps)
  216. {
  217. struct pkginfo *pkg;
  218. while ((pkg = pkg_db_iter_next_pkg(ps->pkg_iter))) {
  219. if (pkg_spec_match_pkg(ps, pkg, &pkg->installed))
  220. return pkg;
  221. }
  222. return NULL;
  223. }
  224. static struct pkginfo *
  225. pkg_spec_iter_next_pkgarch(struct pkg_spec *ps)
  226. {
  227. struct pkginfo *pkg;
  228. while ((pkg = ps->pkg_next)) {
  229. ps->pkg_next = pkg->arch_next;
  230. if (pkg_spec_match_arch(ps, pkg, pkg->installed.arch))
  231. return pkg;
  232. }
  233. return NULL;
  234. }
  235. struct pkginfo *
  236. pkg_spec_iter_next_pkg(struct pkg_spec *ps)
  237. {
  238. if (ps->name_is_pattern)
  239. return pkg_spec_iter_next_pkgname(ps);
  240. else
  241. return pkg_spec_iter_next_pkgarch(ps);
  242. }
  243. void
  244. pkg_spec_iter_destroy(struct pkg_spec *ps)
  245. {
  246. pkg_db_iter_free(ps->pkg_iter);
  247. pkg_spec_iter_blank(ps);
  248. }
  249. void
  250. pkg_spec_destroy(struct pkg_spec *ps)
  251. {
  252. free(ps->name);
  253. pkg_spec_blank(ps);
  254. pkg_spec_iter_destroy(ps);
  255. }