1 /*
2 * libdpkg - Debian packaging suite library routines
3 * pkg-show.c - primitives for pkg information display
4 *
5 * Copyright © 1995,1996 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
7 *
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <compat.h>
24
25 #include <string.h>
26
27 #include <dpkg/macros.h>
28 #include <dpkg/i18n.h>
29 #include <dpkg/dpkg.h>
30 #include <dpkg/dpkg-db.h>
31 #include <dpkg/pkg-show.h>
32
33 static bool
pkgbin_name_needs_arch(const struct pkgbin * pkgbin,enum pkg_name_arch_when pnaw)34 pkgbin_name_needs_arch(const struct pkgbin *pkgbin,
35 enum pkg_name_arch_when pnaw)
36 {
37 if (pkgbin->arch->type == DPKG_ARCH_NONE ||
38 pkgbin->arch->type == DPKG_ARCH_EMPTY)
39 return false;
40
41 switch (pnaw) {
42 case pnaw_never:
43 break;
44 case pnaw_nonambig:
45 if (pkgbin->multiarch == PKG_MULTIARCH_SAME)
46 return true;
47 /* Fall through. */
48 case pnaw_foreign:
49 if (pkgbin->arch->type == DPKG_ARCH_NATIVE ||
50 pkgbin->arch->type == DPKG_ARCH_ALL)
51 break;
52 /* Fall through. */
53 case pnaw_always:
54 return true;
55 }
56
57 return false;
58 }
59
60 /**
61 * Add a string representation of the package name to a varbuf.
62 *
63 * Works exactly like pkgbin_name() but acts on the varbuf instead of
64 * returning a string. It NUL terminates the varbuf.
65 *
66 * @param vb The varbuf struct to modify.
67 * @param pkg The package to consider.
68 * @param pkgbin The binary package instance to consider.
69 * @param pnaw When to display the architecture qualifier.
70 */
71 void
varbuf_add_pkgbin_name(struct varbuf * vb,const struct pkginfo * pkg,const struct pkgbin * pkgbin,enum pkg_name_arch_when pnaw)72 varbuf_add_pkgbin_name(struct varbuf *vb,
73 const struct pkginfo *pkg, const struct pkgbin *pkgbin,
74 enum pkg_name_arch_when pnaw)
75 {
76 varbuf_add_str(vb, pkg->set->name);
77 if (pkgbin_name_needs_arch(pkgbin, pnaw))
78 varbuf_add_archqual(vb, pkgbin->arch);
79 varbuf_end_str(vb);
80 }
81
82 const char *
pkgbin_name_archqual(const struct pkginfo * pkg,const struct pkgbin * pkgbin)83 pkgbin_name_archqual(const struct pkginfo *pkg, const struct pkgbin *pkgbin)
84 {
85 char *pkgname;
86
87 if (pkgbin->arch->type == DPKG_ARCH_NONE ||
88 pkgbin->arch->type == DPKG_ARCH_EMPTY)
89 return pkg->set->name;
90
91 pkgname = nfmalloc(strlen(pkg->set->name) + 1 +
92 strlen(pkgbin->arch->name) + 1);
93 str_concat(pkgname, pkg->set->name, ":",
94 pkgbin->arch->name, NULL);
95
96 return pkgname;
97 }
98
99 /**
100 * Return a string representation of the package name.
101 *
102 * The returned string must not be freed, and it's permanently allocated so
103 * can be used as long as the non-freeing memory pool has not been freed.
104 *
105 * Note, that this const variant will "leak" a new non-freeing string on
106 * each call if the internal cache has not been previously initialized,
107 * so it is advised to use it only in error reporting code paths.
108 *
109 * The pnaw parameter should be one of pnaw_never (never print arch),
110 * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
111 * arch for non ambiguous cases) or pnaw_always (always print arch),
112 *
113 * @param pkg The package to consider.
114 * @param pkgbin The binary package instance to consider.
115 * @param pnaw When to display the architecture qualifier.
116 *
117 * @return The string representation.
118 */
119 const char *
pkgbin_name_const(const struct pkginfo * pkg,const struct pkgbin * pkgbin,enum pkg_name_arch_when pnaw)120 pkgbin_name_const(const struct pkginfo *pkg, const struct pkgbin *pkgbin,
121 enum pkg_name_arch_when pnaw)
122 {
123 if (!pkgbin_name_needs_arch(pkgbin, pnaw))
124 return pkg->set->name;
125
126 /* Return a non-freeing package name representation, which
127 * is intended to be used in error-handling code, as we will keep
128 * "leaking" them until the next memory pool flush. */
129 if (pkgbin->pkgname_archqual == NULL)
130 return pkgbin_name_archqual(pkg, pkgbin);
131
132 return pkgbin->pkgname_archqual;
133 }
134
135 /**
136 * Return a string representation of the installed package name.
137 *
138 * This is equivalent to pkgbin_name_const() but just for its installed pkgbin.
139 *
140 * @param pkg The package to consider.
141 * @param pnaw When to display the architecture qualifier.
142 *
143 * @return The string representation.
144 */
145 const char *
pkg_name_const(const struct pkginfo * pkg,enum pkg_name_arch_when pnaw)146 pkg_name_const(const struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
147 {
148 return pkgbin_name_const(pkg, &pkg->installed, pnaw);
149 }
150
151 /**
152 * Return a string representation of the package name.
153 *
154 * The returned string must not be freed, and it's permanently allocated so
155 * can be used as long as the non-freeing memory pool has not been freed.
156 *
157 * The pnaw parameter should be one of pnaw_never (never print arch),
158 * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
159 * arch for non ambiguous cases) or pnaw_always (always print arch),
160 *
161 * @param pkg The package to consider.
162 * @param pkgbin The binary package instance to consider.
163 * @param pnaw When to display the architecture qualifier.
164 *
165 * @return The string representation.
166 */
167 const char *
pkgbin_name(struct pkginfo * pkg,struct pkgbin * pkgbin,enum pkg_name_arch_when pnaw)168 pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
169 enum pkg_name_arch_when pnaw)
170 {
171 if (!pkgbin_name_needs_arch(pkgbin, pnaw))
172 return pkg->set->name;
173
174 /* Cache the package name representation, for later reuse. */
175 if (pkgbin->pkgname_archqual == NULL)
176 pkgbin->pkgname_archqual = pkgbin_name_archqual(pkg, pkgbin);
177
178 return pkgbin->pkgname_archqual;
179 }
180
181 /**
182 * Return a string representation of the installed package name.
183 *
184 * This is equivalent to pkgbin_name() but just for its installed pkgbin.
185 *
186 * @param pkg The package to consider.
187 * @param pnaw When to display the architecture qualifier.
188 *
189 * @return The string representation.
190 */
191 const char *
pkg_name(struct pkginfo * pkg,enum pkg_name_arch_when pnaw)192 pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
193 {
194 return pkgbin_name(pkg, &pkg->installed, pnaw);
195 }
196
197 /**
198 * Return a string representation of the package synopsis.
199 *
200 * The returned string must not be freed, and it's permanently allocated so
201 * can be used as long as the non-freeing memory pool has not been freed.
202 *
203 * The package synopsis is the short description, but it is not NUL terminated,
204 * so the output len argument should be used to limit the string length.
205 *
206 * @param pkg The package to consider.
207 * @param pkgbin The binary package instance to consider.
208 * @param[out] len The length of the synopsis string within the description.
209 *
210 * @return The string representation.
211 */
212 const char *
pkgbin_synopsis(const struct pkginfo * pkg,const struct pkgbin * pkgbin,int * len)213 pkgbin_synopsis(const struct pkginfo *pkg, const struct pkgbin *pkgbin, int *len)
214 {
215 const char *pdesc;
216
217 pdesc = pkgbin->description;
218 if (!pdesc)
219 pdesc = _("(no description available)");
220
221 *len = strcspn(pdesc, "\n");
222
223 return pdesc;
224 }
225
226 /**
227 * Return a character abbreviated representation of the package want status.
228 *
229 * @param pkg The package to consider.
230 *
231 * @return The character abbreviated representation.
232 */
233 int
pkg_abbrev_want(const struct pkginfo * pkg)234 pkg_abbrev_want(const struct pkginfo *pkg)
235 {
236 return "uihrp"[pkg->want];
237 }
238
239 /**
240 * Return a character abbreviated representation of the package current status.
241 *
242 * @param pkg The package to consider.
243 *
244 * @return The character abbreviated representation.
245 */
246 int
pkg_abbrev_status(const struct pkginfo * pkg)247 pkg_abbrev_status(const struct pkginfo *pkg)
248 {
249 return "ncHUFWti"[pkg->status];
250 }
251
252 /**
253 * Return a character abbreviated representation of the package eflag status.
254 *
255 * @param pkg The package to consider.
256 *
257 * @return The character abbreviated representation.
258 */
259 int
pkg_abbrev_eflag(const struct pkginfo * pkg)260 pkg_abbrev_eflag(const struct pkginfo *pkg)
261 {
262 return " R"[pkg->eflag];
263 }
264
265 /**
266 * Return a string representation of the package want status name.
267 *
268 * @param pkg The package to consider.
269 *
270 * @return The string representation.
271 */
272 const char *
pkg_want_name(const struct pkginfo * pkg)273 pkg_want_name(const struct pkginfo *pkg)
274 {
275 return wantinfos[pkg->want].name;
276 }
277
278 /**
279 * Return a string representation of the package eflag status name.
280 *
281 * @param pkg The package to consider.
282 *
283 * @return The string representation.
284 */
285 const char *
pkg_eflag_name(const struct pkginfo * pkg)286 pkg_eflag_name(const struct pkginfo *pkg)
287 {
288 return eflaginfos[pkg->eflag].name;
289 }
290
291 /**
292 * Return a string representation of the package current status name.
293 *
294 * @param pkg The package to consider.
295 *
296 * @return The string representation.
297 */
298 const char *
pkg_status_name(const struct pkginfo * pkg)299 pkg_status_name(const struct pkginfo *pkg)
300 {
301 return statusinfos[pkg->status].name;
302 }
303
304 /**
305 * Return a string representation of the package priority name.
306 *
307 * @param pkg The package to consider.
308 *
309 * @return The string representation.
310 */
311 const char *
pkg_priority_name(const struct pkginfo * pkg)312 pkg_priority_name(const struct pkginfo *pkg)
313 {
314 if (pkg->priority == PKG_PRIO_OTHER)
315 return pkg->otherpriority;
316 else
317 return priorityinfos[pkg->priority].name;
318 }
319
320 /**
321 * Compare a package to be sorted by non-ambiguous name and architecture.
322 *
323 * @param a A pointer of a pointer to a struct pkginfo.
324 * @param b A pointer of a pointer to a struct pkginfo.
325 *
326 * @return An integer with the result of the comparison.
327 * @retval -1 a is earlier than b.
328 * @retval 0 a is equal to b.
329 * @retval 1 a is later than b.
330 */
331 int
pkg_sorter_by_nonambig_name_arch(const void * a,const void * b)332 pkg_sorter_by_nonambig_name_arch(const void *a, const void *b)
333 {
334 const struct pkginfo *pa = *(const struct pkginfo **)a;
335 const struct pkginfo *pb = *(const struct pkginfo **)b;
336 const struct pkgbin *pbina = &pa->installed;
337 const struct pkgbin *pbinb = &pb->installed;
338 int res;
339
340 res = strcmp(pa->set->name, pb->set->name);
341 if (res)
342 return res;
343
344 if (pbina->arch == pbinb->arch)
345 return 0;
346
347 if (pkgbin_name_needs_arch(pbina, pnaw_nonambig)) {
348 if (pkgbin_name_needs_arch(pbinb, pnaw_nonambig))
349 return strcmp(pbina->arch->name, pbinb->arch->name);
350 else
351 return 1;
352 } else {
353 return -1;
354 }
355 }
356
357 /**
358 * Add a string representation of the source package version to a varbuf.
359 *
360 * It parses the Source field (if present), and extracts the optional
361 * version enclosed in parenthesis. Otherwise it fallsback to use the
362 * binary package version. It NUL terminates the varbuf.
363 *
364 * @param vb The varbuf struct to modify.
365 * @param pkg The package to consider.
366 * @param pkgbin The binary package instance to consider.
367 */
368 void
varbuf_add_source_version(struct varbuf * vb,const struct pkginfo * pkg,const struct pkgbin * pkgbin)369 varbuf_add_source_version(struct varbuf *vb,
370 const struct pkginfo *pkg, const struct pkgbin *pkgbin)
371 {
372 const char *version;
373 size_t len;
374
375 if (pkgbin->source)
376 version = strchr(pkgbin->source, '(');
377 else
378 version = NULL;
379
380 if (version == NULL) {
381 varbufversion(vb, &pkgbin->version, vdew_nonambig);
382 } else {
383 version++;
384
385 len = strcspn(version, ")");
386
387 varbuf_add_buf(vb, version, len);
388 }
389 }
390
391 void
pkg_source_version(struct dpkg_version * version,const struct pkginfo * pkg,const struct pkgbin * pkgbin)392 pkg_source_version(struct dpkg_version *version,
393 const struct pkginfo *pkg, const struct pkgbin *pkgbin)
394 {
395 struct dpkg_error err;
396 struct varbuf vb = VARBUF_INIT;
397
398 varbuf_add_source_version(&vb, pkg, pkgbin);
399 varbuf_end_str(&vb);
400
401 if (parseversion(version, vb.buf, &err) < 0)
402 ohshit(_("version '%s' has bad syntax: %s"), vb.buf, err.str);
403 }
404