pkg-spec.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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-2014 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. snprintf(msg, sizeof(msg),
  61. _("illegal package name in specifier '%s%s%s': %s"),
  62. ps->name,
  63. (ps->arch->type != DPKG_ARCH_NONE) ? ":" : "",
  64. ps->arch->name, emsg);
  65. return msg;
  66. }
  67. if ((!ps->arch_is_pattern && ps->arch->type == DPKG_ARCH_ILLEGAL) ||
  68. ps->arch->type == DPKG_ARCH_EMPTY) {
  69. emsg = dpkg_arch_name_is_illegal(ps->arch->name);
  70. snprintf(msg, sizeof(msg),
  71. _("illegal architecture name in specifier '%s:%s': %s"),
  72. ps->name, ps->arch->name, emsg);
  73. return msg;
  74. }
  75. /* If we have been requested a single instance, check that the
  76. * package does not contain other instances. */
  77. if (!ps->arch_is_pattern && ps->flags & PKG_SPEC_ARCH_SINGLE) {
  78. struct pkgset *set;
  79. set = pkg_db_find_set(ps->name);
  80. /* Single instancing only applies with no architecture. */
  81. if (ps->arch->type == DPKG_ARCH_NONE &&
  82. pkgset_installed_instances(set) > 1) {
  83. snprintf(msg, sizeof(msg),
  84. _("ambiguous package name '%s' with more "
  85. "than one installed instance"), ps->name);
  86. return msg;
  87. }
  88. }
  89. return NULL;
  90. }
  91. static const char *
  92. pkg_spec_prep(struct pkg_spec *ps, char *pkgname, const char *archname)
  93. {
  94. ps->name = pkgname;
  95. ps->arch = dpkg_arch_find(archname);
  96. ps->name_is_pattern = false;
  97. ps->arch_is_pattern = false;
  98. /* Detect if we have patterns and/or illegal names. */
  99. if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->name, "*[?\\"))
  100. ps->name_is_pattern = true;
  101. if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->arch->name, "*[?\\"))
  102. ps->arch_is_pattern = true;
  103. return pkg_spec_is_illegal(ps);
  104. }
  105. const char *
  106. pkg_spec_set(struct pkg_spec *ps, const char *pkgname, const char *archname)
  107. {
  108. return pkg_spec_prep(ps, m_strdup(pkgname), archname);
  109. }
  110. const char *
  111. pkg_spec_parse(struct pkg_spec *ps, const char *str)
  112. {
  113. char *pkgname, *archname;
  114. archname = strchr(str, ':');
  115. if (archname == NULL) {
  116. pkgname = m_strdup(str);
  117. } else {
  118. pkgname = m_strndup(str, archname - str);
  119. archname++;
  120. }
  121. return pkg_spec_prep(ps, pkgname, archname);
  122. }
  123. static bool
  124. pkg_spec_match_name(struct pkg_spec *ps, const char *name)
  125. {
  126. if (ps->name_is_pattern)
  127. return (fnmatch(ps->name, name, 0) == 0);
  128. else
  129. return (strcmp(ps->name, name) == 0);
  130. }
  131. static bool
  132. pkg_spec_match_arch(struct pkg_spec *ps, struct pkginfo *pkg,
  133. const struct dpkg_arch *arch)
  134. {
  135. if (ps->arch_is_pattern)
  136. return (fnmatch(ps->arch->name, arch->name, 0) == 0);
  137. else if (ps->arch->type != DPKG_ARCH_NONE) /* !arch_is_pattern */
  138. return (ps->arch == arch);
  139. /* No arch specified. */
  140. switch (ps->flags & PKG_SPEC_ARCH_MASK) {
  141. case PKG_SPEC_ARCH_SINGLE:
  142. return pkgset_installed_instances(pkg->set) <= 1;
  143. case PKG_SPEC_ARCH_WILDCARD:
  144. return true;
  145. default:
  146. internerr("unknown PKG_SPEC_ARCH_* flags %d in pkg_spec",
  147. ps->flags & PKG_SPEC_ARCH_MASK);
  148. }
  149. }
  150. bool
  151. pkg_spec_match_pkg(struct pkg_spec *ps, struct pkginfo *pkg,
  152. struct pkgbin *pkgbin)
  153. {
  154. return (pkg_spec_match_name(ps, pkg->set->name) &&
  155. pkg_spec_match_arch(ps, pkg, pkgbin->arch));
  156. }
  157. static struct pkginfo *
  158. pkg_spec_get_pkg(struct pkg_spec *ps)
  159. {
  160. if (ps->arch->type == DPKG_ARCH_NONE)
  161. return pkg_db_find_singleton(ps->name);
  162. else
  163. return pkg_db_find_pkg(ps->name, ps->arch);
  164. }
  165. struct pkginfo *
  166. pkg_spec_parse_pkg(const char *str, struct dpkg_error *err)
  167. {
  168. struct pkg_spec ps;
  169. struct pkginfo *pkg;
  170. const char *emsg;
  171. pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
  172. emsg = pkg_spec_parse(&ps, str);
  173. if (emsg) {
  174. dpkg_put_error(err, "%s", emsg);
  175. pkg = NULL;
  176. } else {
  177. pkg = pkg_spec_get_pkg(&ps);
  178. }
  179. pkg_spec_destroy(&ps);
  180. return pkg;
  181. }
  182. struct pkginfo *
  183. pkg_spec_find_pkg(const char *pkgname, const char *archname,
  184. struct dpkg_error *err)
  185. {
  186. struct pkg_spec ps;
  187. struct pkginfo *pkg;
  188. const char *emsg;
  189. pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
  190. emsg = pkg_spec_set(&ps, pkgname, archname);
  191. if (emsg) {
  192. dpkg_put_error(err, "%s", emsg);
  193. pkg = NULL;
  194. } else {
  195. pkg = pkg_spec_get_pkg(&ps);
  196. }
  197. pkg_spec_destroy(&ps);
  198. return pkg;
  199. }
  200. void
  201. pkg_spec_iter_init(struct pkg_spec *ps)
  202. {
  203. if (ps->name_is_pattern)
  204. ps->pkg_iter = pkg_db_iter_new();
  205. else
  206. ps->pkg_next = &pkg_db_find_set(ps->name)->pkg;
  207. }
  208. static struct pkginfo *
  209. pkg_spec_iter_next_pkgname(struct pkg_spec *ps)
  210. {
  211. struct pkginfo *pkg;
  212. while ((pkg = pkg_db_iter_next_pkg(ps->pkg_iter))) {
  213. if (pkg_spec_match_pkg(ps, pkg, &pkg->installed))
  214. return pkg;
  215. }
  216. return NULL;
  217. }
  218. static struct pkginfo *
  219. pkg_spec_iter_next_pkgarch(struct pkg_spec *ps)
  220. {
  221. struct pkginfo *pkg;
  222. while ((pkg = ps->pkg_next)) {
  223. ps->pkg_next = pkg->arch_next;
  224. if (pkg_spec_match_arch(ps, pkg, pkg->installed.arch))
  225. return pkg;
  226. }
  227. return NULL;
  228. }
  229. struct pkginfo *
  230. pkg_spec_iter_next_pkg(struct pkg_spec *ps)
  231. {
  232. if (ps->name_is_pattern)
  233. return pkg_spec_iter_next_pkgname(ps);
  234. else
  235. return pkg_spec_iter_next_pkgarch(ps);
  236. }
  237. void
  238. pkg_spec_iter_destroy(struct pkg_spec *ps)
  239. {
  240. pkg_db_iter_free(ps->pkg_iter);
  241. pkg_spec_iter_blank(ps);
  242. }
  243. void
  244. pkg_spec_destroy(struct pkg_spec *ps)
  245. {
  246. free(ps->name);
  247. pkg_spec_blank(ps);
  248. pkg_spec_iter_destroy(ps);
  249. }