Branch data Line data Source code
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 : :
23 : : #include <config.h>
24 : : #include <compat.h>
25 : :
26 : : #include <stdlib.h>
27 : : #include <fnmatch.h>
28 : : #include <string.h>
29 : :
30 : : #include <dpkg/i18n.h>
31 : : #include <dpkg/dpkg.h>
32 : : #include <dpkg/dpkg-db.h>
33 : : #include <dpkg/arch.h>
34 : : #include <dpkg/pkg-spec.h>
35 : :
36 : : static void
37 : 0 : pkg_spec_blank(struct pkg_spec *ps)
38 : : {
39 : 0 : ps->name = NULL;
40 : 0 : ps->arch = NULL;
41 : :
42 : 0 : ps->name_is_pattern = false;
43 : 0 : ps->arch_is_pattern = false;
44 : 0 : }
45 : :
46 : : static void
47 : 0 : pkg_spec_iter_blank(struct pkg_spec *ps)
48 : : {
49 : 0 : ps->pkg_iter = NULL;
50 : 0 : ps->pkg_next = NULL;
51 : 0 : }
52 : :
53 : : void
54 : 0 : pkg_spec_init(struct pkg_spec *ps, enum pkg_spec_flags flags)
55 : : {
56 : 0 : ps->flags = flags;
57 : :
58 : 0 : pkg_spec_blank(ps);
59 : 0 : pkg_spec_iter_blank(ps);
60 : 0 : }
61 : :
62 : : const char *
63 : 0 : pkg_spec_is_illegal(struct pkg_spec *ps)
64 : : {
65 : : static char msg[1024];
66 : : const char *emsg;
67 : :
68 [ # # # # ]: 0 : if (!ps->name_is_pattern &&
69 : 0 : (emsg = pkg_name_is_illegal(ps->name))) {
70 : : const char *arch_sep;
71 : :
72 : : /* Only check for DPKG_ARCH_NONE, because for everything else
73 : : * we want to see the passed package specification, even if
74 : : * the architecture is empty. */
75 [ # # ]: 0 : if (ps->arch->type == DPKG_ARCH_NONE)
76 : 0 : arch_sep = "";
77 : : else
78 : 0 : arch_sep = ":";
79 : :
80 : 0 : snprintf(msg, sizeof(msg),
81 : 0 : _("illegal package name in specifier '%s%s%s': %s"),
82 : 0 : ps->name, arch_sep, ps->arch->name, emsg);
83 : 0 : return msg;
84 : : }
85 : :
86 [ # # # # ]: 0 : if ((!ps->arch_is_pattern && ps->arch->type == DPKG_ARCH_ILLEGAL) ||
87 [ # # ]: 0 : ps->arch->type == DPKG_ARCH_EMPTY) {
88 : 0 : emsg = dpkg_arch_name_is_illegal(ps->arch->name);
89 : 0 : snprintf(msg, sizeof(msg),
90 : 0 : _("illegal architecture name in specifier '%s:%s': %s"),
91 : 0 : ps->name, ps->arch->name, emsg);
92 : 0 : return msg;
93 : : }
94 : :
95 : : /* If we have been requested a single instance, check that the
96 : : * package does not contain other instances. */
97 [ # # # # ]: 0 : if (!ps->arch_is_pattern && ps->flags & PKG_SPEC_ARCH_SINGLE) {
98 : : struct pkgset *set;
99 : :
100 : 0 : set = pkg_hash_find_set(ps->name);
101 : :
102 : : /* Single instancing only applies with no architecture. */
103 [ # # # # ]: 0 : if (ps->arch->type == DPKG_ARCH_NONE &&
104 : 0 : pkgset_installed_instances(set) > 1) {
105 : 0 : snprintf(msg, sizeof(msg),
106 : 0 : _("ambiguous package name '%s' with more "
107 : : "than one installed instance"), ps->name);
108 : 0 : return msg;
109 : : }
110 : : }
111 : :
112 : 0 : return NULL;
113 : : }
114 : :
115 : : static const char *
116 : 0 : pkg_spec_prep(struct pkg_spec *ps, char *pkgname, const char *archname)
117 : : {
118 : 0 : ps->name = pkgname;
119 : 0 : ps->arch = dpkg_arch_find(archname);
120 : :
121 : 0 : ps->name_is_pattern = false;
122 : 0 : ps->arch_is_pattern = false;
123 : :
124 : : /* Detect if we have patterns and/or illegal names. */
125 [ # # # # ]: 0 : if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->name, "*[?\\"))
126 : 0 : ps->name_is_pattern = true;
127 : :
128 [ # # # # ]: 0 : if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->arch->name, "*[?\\"))
129 : 0 : ps->arch_is_pattern = true;
130 : :
131 : 0 : return pkg_spec_is_illegal(ps);
132 : : }
133 : :
134 : : const char *
135 : 0 : pkg_spec_set(struct pkg_spec *ps, const char *pkgname, const char *archname)
136 : : {
137 : 0 : return pkg_spec_prep(ps, m_strdup(pkgname), archname);
138 : : }
139 : :
140 : : const char *
141 : 0 : pkg_spec_parse(struct pkg_spec *ps, const char *str)
142 : : {
143 : : char *pkgname, *archname;
144 : :
145 : 0 : archname = strchr(str, ':');
146 [ # # ]: 0 : if (archname == NULL) {
147 : 0 : pkgname = m_strdup(str);
148 : : } else {
149 : 0 : pkgname = m_strndup(str, archname - str);
150 : 0 : archname++;
151 : : }
152 : :
153 : 0 : return pkg_spec_prep(ps, pkgname, archname);
154 : : }
155 : :
156 : : static bool
157 : 0 : pkg_spec_match_name(struct pkg_spec *ps, const char *name)
158 : : {
159 [ # # ]: 0 : if (ps->name_is_pattern)
160 : 0 : return (fnmatch(ps->name, name, 0) == 0);
161 : : else
162 : 0 : return (strcmp(ps->name, name) == 0);
163 : : }
164 : :
165 : : static bool
166 : 0 : pkg_spec_match_arch(struct pkg_spec *ps, struct pkginfo *pkg,
167 : : const struct dpkg_arch *arch)
168 : : {
169 [ # # ]: 0 : if (ps->arch_is_pattern)
170 : 0 : return (fnmatch(ps->arch->name, arch->name, 0) == 0);
171 [ # # ]: 0 : else if (ps->arch->type != DPKG_ARCH_NONE) /* !arch_is_pattern */
172 : 0 : return (ps->arch == arch);
173 : :
174 : : /* No arch specified. */
175 [ # # # ]: 0 : switch (ps->flags & PKG_SPEC_ARCH_MASK) {
176 : 0 : case PKG_SPEC_ARCH_SINGLE:
177 : 0 : return pkgset_installed_instances(pkg->set) <= 1;
178 : 0 : case PKG_SPEC_ARCH_WILDCARD:
179 : 0 : return true;
180 : 0 : default:
181 : 0 : internerr("unknown PKG_SPEC_ARCH_* flags %d in pkg_spec",
182 : : ps->flags & PKG_SPEC_ARCH_MASK);
183 : : }
184 : : }
185 : :
186 : : bool
187 : 0 : pkg_spec_match_pkg(struct pkg_spec *ps, struct pkginfo *pkg,
188 : : struct pkgbin *pkgbin)
189 : : {
190 [ # # # # ]: 0 : return (pkg_spec_match_name(ps, pkg->set->name) &&
191 : 0 : pkg_spec_match_arch(ps, pkg, pkgbin->arch));
192 : : }
193 : :
194 : : static struct pkginfo *
195 : 0 : pkg_spec_get_pkg(struct pkg_spec *ps)
196 : : {
197 [ # # ]: 0 : if (ps->arch->type == DPKG_ARCH_NONE)
198 : 0 : return pkg_hash_find_singleton(ps->name);
199 : : else
200 : 0 : return pkg_hash_find_pkg(ps->name, ps->arch);
201 : : }
202 : :
203 : : struct pkginfo *
204 : 0 : pkg_spec_parse_pkg(const char *str, struct dpkg_error *err)
205 : : {
206 : : struct pkg_spec ps;
207 : : struct pkginfo *pkg;
208 : : const char *emsg;
209 : :
210 : 0 : pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
211 : 0 : emsg = pkg_spec_parse(&ps, str);
212 [ # # ]: 0 : if (emsg) {
213 : 0 : dpkg_put_error(err, "%s", emsg);
214 : 0 : pkg = NULL;
215 : : } else {
216 : 0 : pkg = pkg_spec_get_pkg(&ps);
217 : : }
218 : 0 : pkg_spec_destroy(&ps);
219 : :
220 : 0 : return pkg;
221 : : }
222 : :
223 : : struct pkginfo *
224 : 0 : pkg_spec_find_pkg(const char *pkgname, const char *archname,
225 : : struct dpkg_error *err)
226 : : {
227 : : struct pkg_spec ps;
228 : : struct pkginfo *pkg;
229 : : const char *emsg;
230 : :
231 : 0 : pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
232 : 0 : emsg = pkg_spec_set(&ps, pkgname, archname);
233 [ # # ]: 0 : if (emsg) {
234 : 0 : dpkg_put_error(err, "%s", emsg);
235 : 0 : pkg = NULL;
236 : : } else {
237 : 0 : pkg = pkg_spec_get_pkg(&ps);
238 : : }
239 : 0 : pkg_spec_destroy(&ps);
240 : :
241 : 0 : return pkg;
242 : : }
243 : :
244 : : void
245 : 0 : pkg_spec_iter_init(struct pkg_spec *ps)
246 : : {
247 [ # # ]: 0 : if (ps->name_is_pattern)
248 : 0 : ps->pkg_iter = pkg_hash_iter_new();
249 : : else
250 : 0 : ps->pkg_next = &pkg_hash_find_set(ps->name)->pkg;
251 : 0 : }
252 : :
253 : : static struct pkginfo *
254 : 0 : pkg_spec_iter_next_pkgname(struct pkg_spec *ps)
255 : : {
256 : : struct pkginfo *pkg;
257 : :
258 [ # # ]: 0 : while ((pkg = pkg_hash_iter_next_pkg(ps->pkg_iter))) {
259 [ # # ]: 0 : if (pkg_spec_match_pkg(ps, pkg, &pkg->installed))
260 : 0 : return pkg;
261 : : }
262 : :
263 : 0 : return NULL;
264 : : }
265 : :
266 : : static struct pkginfo *
267 : 0 : pkg_spec_iter_next_pkgarch(struct pkg_spec *ps)
268 : : {
269 : : struct pkginfo *pkg;
270 : :
271 [ # # ]: 0 : while ((pkg = ps->pkg_next)) {
272 : 0 : ps->pkg_next = pkg->arch_next;
273 : :
274 [ # # ]: 0 : if (pkg_spec_match_arch(ps, pkg, pkg->installed.arch))
275 : 0 : return pkg;
276 : : }
277 : :
278 : 0 : return NULL;
279 : : }
280 : :
281 : : struct pkginfo *
282 : 0 : pkg_spec_iter_next_pkg(struct pkg_spec *ps)
283 : : {
284 [ # # ]: 0 : if (ps->name_is_pattern)
285 : 0 : return pkg_spec_iter_next_pkgname(ps);
286 : : else
287 : 0 : return pkg_spec_iter_next_pkgarch(ps);
288 : : }
289 : :
290 : : void
291 : 0 : pkg_spec_iter_destroy(struct pkg_spec *ps)
292 : : {
293 : 0 : pkg_hash_iter_free(ps->pkg_iter);
294 : 0 : pkg_spec_iter_blank(ps);
295 : 0 : }
296 : :
297 : : void
298 : 0 : pkg_spec_destroy(struct pkg_spec *ps)
299 : : {
300 : 0 : free(ps->name);
301 : 0 : pkg_spec_blank(ps);
302 : 0 : pkg_spec_iter_destroy(ps);
303 : 0 : }
|