pkg-spec.c 6.6 KB

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