po: Update German man pages translation
[dpkg.git] / lib / dpkg / pkg-spec.c
blob3e3f59fa0d47c5c9be1a43306252ff3891cd50bf
1 /*
2 * libdpkg - Debian packaging suite library routines
3 * pkg-spec.c - primitives for pkg specifier handling
5 * Copyright © 2011 Linaro Limited
6 * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
7 * Copyright © 2011-2015 Guillem Jover <guillem@debian.org>
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.
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.
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/>.
23 #include <config.h>
24 #include <compat.h>
26 #include <stdlib.h>
27 #include <fnmatch.h>
28 #include <string.h>
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>
36 static void
37 pkg_spec_blank(struct pkg_spec *ps)
39 ps->name = NULL;
40 ps->arch = NULL;
42 ps->name_is_pattern = false;
43 ps->arch_is_pattern = false;
46 static void
47 pkg_spec_iter_blank(struct pkg_spec *ps)
49 ps->pkg_iter = NULL;
50 ps->pkg_next = NULL;
53 void
54 pkg_spec_init(struct pkg_spec *ps, enum pkg_spec_flags flags)
56 ps->flags = flags;
58 pkg_spec_blank(ps);
59 pkg_spec_iter_blank(ps);
62 const char *
63 pkg_spec_is_illegal(struct pkg_spec *ps)
65 static char msg[1024];
66 const char *emsg;
68 if (!ps->name_is_pattern &&
69 (emsg = pkg_name_is_illegal(ps->name))) {
70 const char *arch_sep;
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 if (ps->arch->type == DPKG_ARCH_NONE)
76 arch_sep = "";
77 else
78 arch_sep = ":";
80 snprintf(msg, sizeof(msg),
81 _("illegal package name in specifier '%s%s%s': %s"),
82 ps->name, arch_sep, ps->arch->name, emsg);
83 return msg;
86 if ((!ps->arch_is_pattern && ps->arch->type == DPKG_ARCH_ILLEGAL) ||
87 ps->arch->type == DPKG_ARCH_EMPTY) {
88 emsg = dpkg_arch_name_is_illegal(ps->arch->name);
89 snprintf(msg, sizeof(msg),
90 _("illegal architecture name in specifier '%s:%s': %s"),
91 ps->name, ps->arch->name, emsg);
92 return msg;
95 /* If we have been requested a single instance, check that the
96 * package does not contain other instances. */
97 if (!ps->arch_is_pattern && ps->flags & PKG_SPEC_ARCH_SINGLE) {
98 struct pkgset *set;
100 set = pkg_hash_find_set(ps->name);
102 /* Single instancing only applies with no architecture. */
103 if (ps->arch->type == DPKG_ARCH_NONE &&
104 pkgset_installed_instances(set) > 1) {
105 snprintf(msg, sizeof(msg),
106 _("ambiguous package name '%s' with more "
107 "than one installed instance"), ps->name);
108 return msg;
112 return NULL;
115 static const char *
116 pkg_spec_prep(struct pkg_spec *ps, char *pkgname, const char *archname)
118 ps->name = pkgname;
119 ps->arch = dpkg_arch_find(archname);
121 ps->name_is_pattern = false;
122 ps->arch_is_pattern = false;
124 /* Detect if we have patterns and/or illegal names. */
125 if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->name, "*[?\\"))
126 ps->name_is_pattern = true;
128 if ((ps->flags & PKG_SPEC_PATTERNS) && strpbrk(ps->arch->name, "*[?\\"))
129 ps->arch_is_pattern = true;
131 return pkg_spec_is_illegal(ps);
134 const char *
135 pkg_spec_set(struct pkg_spec *ps, const char *pkgname, const char *archname)
137 return pkg_spec_prep(ps, m_strdup(pkgname), archname);
140 const char *
141 pkg_spec_parse(struct pkg_spec *ps, const char *str)
143 char *pkgname, *archname;
145 archname = strchr(str, ':');
146 if (archname == NULL) {
147 pkgname = m_strdup(str);
148 } else {
149 pkgname = m_strndup(str, archname - str);
150 archname++;
153 return pkg_spec_prep(ps, pkgname, archname);
156 static bool
157 pkg_spec_match_name(struct pkg_spec *ps, const char *name)
159 if (ps->name_is_pattern)
160 return (fnmatch(ps->name, name, 0) == 0);
161 else
162 return (strcmp(ps->name, name) == 0);
165 static bool
166 pkg_spec_match_arch(struct pkg_spec *ps, struct pkginfo *pkg,
167 const struct dpkg_arch *arch)
169 if (ps->arch_is_pattern)
170 return (fnmatch(ps->arch->name, arch->name, 0) == 0);
171 else if (ps->arch->type != DPKG_ARCH_NONE) /* !arch_is_pattern */
172 return (ps->arch == arch);
174 /* No arch specified. */
175 switch (ps->flags & PKG_SPEC_ARCH_MASK) {
176 case PKG_SPEC_ARCH_SINGLE:
177 return pkgset_installed_instances(pkg->set) <= 1;
178 case PKG_SPEC_ARCH_WILDCARD:
179 return true;
180 default:
181 internerr("unknown PKG_SPEC_ARCH_* flags %d in pkg_spec",
182 ps->flags & PKG_SPEC_ARCH_MASK);
186 bool
187 pkg_spec_match_pkg(struct pkg_spec *ps, struct pkginfo *pkg,
188 struct pkgbin *pkgbin)
190 return (pkg_spec_match_name(ps, pkg->set->name) &&
191 pkg_spec_match_arch(ps, pkg, pkgbin->arch));
194 static struct pkginfo *
195 pkg_spec_get_pkg(struct pkg_spec *ps)
197 if (ps->arch->type == DPKG_ARCH_NONE)
198 return pkg_hash_find_singleton(ps->name);
199 else
200 return pkg_hash_find_pkg(ps->name, ps->arch);
203 struct pkginfo *
204 pkg_spec_parse_pkg(const char *str, struct dpkg_error *err)
206 struct pkg_spec ps;
207 struct pkginfo *pkg;
208 const char *emsg;
210 pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
211 emsg = pkg_spec_parse(&ps, str);
212 if (emsg) {
213 dpkg_put_error(err, "%s", emsg);
214 pkg = NULL;
215 } else {
216 pkg = pkg_spec_get_pkg(&ps);
218 pkg_spec_destroy(&ps);
220 return pkg;
223 struct pkginfo *
224 pkg_spec_find_pkg(const char *pkgname, const char *archname,
225 struct dpkg_error *err)
227 struct pkg_spec ps;
228 struct pkginfo *pkg;
229 const char *emsg;
231 pkg_spec_init(&ps, PKG_SPEC_ARCH_SINGLE);
232 emsg = pkg_spec_set(&ps, pkgname, archname);
233 if (emsg) {
234 dpkg_put_error(err, "%s", emsg);
235 pkg = NULL;
236 } else {
237 pkg = pkg_spec_get_pkg(&ps);
239 pkg_spec_destroy(&ps);
241 return pkg;
244 void
245 pkg_spec_iter_init(struct pkg_spec *ps)
247 if (ps->name_is_pattern)
248 ps->pkg_iter = pkg_hash_iter_new();
249 else
250 ps->pkg_next = &pkg_hash_find_set(ps->name)->pkg;
253 static struct pkginfo *
254 pkg_spec_iter_next_pkgname(struct pkg_spec *ps)
256 struct pkginfo *pkg;
258 while ((pkg = pkg_hash_iter_next_pkg(ps->pkg_iter))) {
259 if (pkg_spec_match_pkg(ps, pkg, &pkg->installed))
260 return pkg;
263 return NULL;
266 static struct pkginfo *
267 pkg_spec_iter_next_pkgarch(struct pkg_spec *ps)
269 struct pkginfo *pkg;
271 while ((pkg = ps->pkg_next)) {
272 ps->pkg_next = pkg->arch_next;
274 if (pkg_spec_match_arch(ps, pkg, pkg->installed.arch))
275 return pkg;
278 return NULL;
281 struct pkginfo *
282 pkg_spec_iter_next_pkg(struct pkg_spec *ps)
284 if (ps->name_is_pattern)
285 return pkg_spec_iter_next_pkgname(ps);
286 else
287 return pkg_spec_iter_next_pkgarch(ps);
290 void
291 pkg_spec_iter_destroy(struct pkg_spec *ps)
293 pkg_hash_iter_free(ps->pkg_iter);
294 pkg_spec_iter_blank(ps);
297 void
298 pkg_spec_destroy(struct pkg_spec *ps)
300 free(ps->name);
301 pkg_spec_blank(ps);
302 pkg_spec_iter_destroy(ps);