Branch data Line data Source code
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
34 : 13 : pkgbin_name_needs_arch(const struct pkgbin *pkgbin,
35 : : enum pkg_name_arch_when pnaw)
36 : : {
37 [ + + ]: 13 : if (pkgbin->arch->type == DPKG_ARCH_NONE ||
38 [ - + ]: 5 : pkgbin->arch->type == DPKG_ARCH_EMPTY)
39 : 8 : return false;
40 : :
41 [ + + + - : 5 : switch (pnaw) {
+ - ]
42 : 1 : case pnaw_never:
43 : 1 : break;
44 : 2 : case pnaw_same:
45 [ + + ]: 2 : if (pkgbin->multiarch == PKG_MULTIARCH_SAME)
46 : 1 : return true;
47 : 1 : return false;
48 : 1 : case pnaw_nonambig:
49 [ - + ]: 1 : if (pkgbin->multiarch == PKG_MULTIARCH_SAME)
50 : 0 : return true;
51 : : /* Fall through. */
52 : : case pnaw_foreign:
53 [ + - ]: 1 : if (pkgbin->arch->type == DPKG_ARCH_NATIVE ||
54 [ + - ]: 1 : pkgbin->arch->type == DPKG_ARCH_ALL)
55 : : break;
56 : : /* Fall through. */
57 : : case pnaw_always:
58 : 2 : return true;
59 : : }
60 : :
61 : 1 : return false;
62 : : }
63 : :
64 : : /**
65 : : * Add a string representation of the package name to a varbuf.
66 : : *
67 : : * Works exactly like pkgbin_name() but acts on the varbuf instead of
68 : : * returning a string. It NUL terminates the varbuf.
69 : : *
70 : : * @param vb The varbuf struct to modify.
71 : : * @param pkg The package to consider.
72 : : * @param pkgbin The binary package instance to consider.
73 : : * @param pnaw When to display the architecture qualifier.
74 : : */
75 : : void
76 : 0 : varbuf_add_pkgbin_name(struct varbuf *vb,
77 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin,
78 : : enum pkg_name_arch_when pnaw)
79 : : {
80 : 0 : varbuf_add_str(vb, pkg->set->name);
81 [ # # ]: 0 : if (pkgbin_name_needs_arch(pkgbin, pnaw))
82 : 0 : varbuf_add_archqual(vb, pkgbin->arch);
83 : 0 : }
84 : :
85 : : const char *
86 : 33 : pkgbin_name_archqual(const struct pkginfo *pkg, const struct pkgbin *pkgbin)
87 : : {
88 : : char *pkgname;
89 : :
90 [ + - ]: 33 : if (pkgbin->arch->type == DPKG_ARCH_NONE ||
91 [ - + ]: 33 : pkgbin->arch->type == DPKG_ARCH_EMPTY)
92 : 0 : return pkg->set->name;
93 : :
94 : 33 : pkgname = nfmalloc(strlen(pkg->set->name) + 1 +
95 : 33 : strlen(pkgbin->arch->name) + 1);
96 : 33 : str_concat(pkgname, pkg->set->name, ":",
97 : 33 : pkgbin->arch->name, NULL);
98 : :
99 : 33 : return pkgname;
100 : : }
101 : :
102 : : /**
103 : : * Return a string representation of the package name.
104 : : *
105 : : * The returned string must not be freed, and it's permanently allocated so
106 : : * can be used as long as the non-freeing memory pool has not been freed.
107 : : *
108 : : * Note, that this const variant will "leak" a new non-freeing string on
109 : : * each call if the internal cache has not been previously initialized,
110 : : * so it is advised to use it only in error reporting code paths.
111 : : *
112 : : * The pnaw parameter should be one of pnaw_never (never print arch),
113 : : * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
114 : : * arch for non ambiguous cases) or pnaw_always (always print arch),
115 : : *
116 : : * @param pkg The package to consider.
117 : : * @param pkgbin The binary package instance to consider.
118 : : * @param pnaw When to display the architecture qualifier.
119 : : *
120 : : * @return The string representation.
121 : : */
122 : : const char *
123 : 0 : pkgbin_name_const(const struct pkginfo *pkg, const struct pkgbin *pkgbin,
124 : : enum pkg_name_arch_when pnaw)
125 : : {
126 [ # # ]: 0 : if (!pkgbin_name_needs_arch(pkgbin, pnaw))
127 : 0 : return pkg->set->name;
128 : :
129 : : /* Return a non-freeing package name representation, which
130 : : * is intended to be used in error-handling code, as we will keep
131 : : * "leaking" them until the next memory pool flush. */
132 [ # # ]: 0 : if (pkgbin->pkgname_archqual == NULL)
133 : 0 : return pkgbin_name_archqual(pkg, pkgbin);
134 : :
135 : 0 : return pkgbin->pkgname_archqual;
136 : : }
137 : :
138 : : /**
139 : : * Return a string representation of the installed package name.
140 : : *
141 : : * This is equivalent to pkgbin_name_const() but just for its installed pkgbin.
142 : : *
143 : : * @param pkg The package to consider.
144 : : * @param pnaw When to display the architecture qualifier.
145 : : *
146 : : * @return The string representation.
147 : : */
148 : : const char *
149 : 0 : pkg_name_const(const struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
150 : : {
151 : 0 : return pkgbin_name_const(pkg, &pkg->installed, pnaw);
152 : : }
153 : :
154 : : /**
155 : : * Return a string representation of the package name.
156 : : *
157 : : * The returned string must not be freed, and it's permanently allocated so
158 : : * can be used as long as the non-freeing memory pool has not been freed.
159 : : *
160 : : * The pnaw parameter should be one of pnaw_never (never print arch),
161 : : * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
162 : : * arch for non ambiguous cases) or pnaw_always (always print arch),
163 : : *
164 : : * @param pkg The package to consider.
165 : : * @param pkgbin The binary package instance to consider.
166 : : * @param pnaw When to display the architecture qualifier.
167 : : *
168 : : * @return The string representation.
169 : : */
170 : : const char *
171 : 13 : pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
172 : : enum pkg_name_arch_when pnaw)
173 : : {
174 [ + + ]: 13 : if (!pkgbin_name_needs_arch(pkgbin, pnaw))
175 : 10 : return pkg->set->name;
176 : :
177 : : /* Cache the package name representation, for later reuse. */
178 [ + + ]: 3 : if (pkgbin->pkgname_archqual == NULL)
179 : 1 : pkgbin->pkgname_archqual = pkgbin_name_archqual(pkg, pkgbin);
180 : :
181 : 3 : return pkgbin->pkgname_archqual;
182 : : }
183 : :
184 : : /**
185 : : * Return a string representation of the installed package name.
186 : : *
187 : : * This is equivalent to pkgbin_name() but just for its installed pkgbin.
188 : : *
189 : : * @param pkg The package to consider.
190 : : * @param pnaw When to display the architecture qualifier.
191 : : *
192 : : * @return The string representation.
193 : : */
194 : : const char *
195 : 5 : pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
196 : : {
197 : 5 : return pkgbin_name(pkg, &pkg->installed, pnaw);
198 : : }
199 : :
200 : : /**
201 : : * Return a string representation of the package synopsis.
202 : : *
203 : : * The returned string must not be freed, and it's permanently allocated so
204 : : * can be used as long as the non-freeing memory pool has not been freed.
205 : : *
206 : : * The package synopsis is the short description, but it is not NUL terminated,
207 : : * so the output len argument should be used to limit the string length.
208 : : *
209 : : * @param pkg The package to consider.
210 : : * @param pkgbin The binary package instance to consider.
211 : : * @param[out] len The length of the synopsis string within the description.
212 : : *
213 : : * @return The string representation.
214 : : */
215 : : const char *
216 : 2 : pkgbin_synopsis(const struct pkginfo *pkg, const struct pkgbin *pkgbin, int *len)
217 : : {
218 : : const char *pdesc;
219 : :
220 : 2 : pdesc = pkgbin->description;
221 [ - + ]: 2 : if (!pdesc)
222 : 0 : pdesc = _("(no description available)");
223 : :
224 : 2 : *len = strcspn(pdesc, "\n");
225 : :
226 : 2 : return pdesc;
227 : : }
228 : :
229 : : /**
230 : : * Return a string representation of the package synopsis.
231 : : *
232 : : * The returned string must not be freed, and it's permanently allocated so
233 : : * can be used as long as the non-freeing memory pool has not been freed.
234 : : *
235 : : * It will try to use the installed version, otherwise it will fallback to
236 : : * use the available version.
237 : : *
238 : : * The package synopsis is the short description, but it is not NUL terminated,
239 : : * so the output len argument should be used to limit the string length.
240 : : *
241 : : * @param pkg The package to consider.
242 : : * @param[out] len The length of the synopsis string within the description.
243 : : *
244 : : * @return The string representation.
245 : : */
246 : : const char *
247 : 0 : pkg_synopsis(const struct pkginfo *pkg, int *len)
248 : : {
249 : : const char *pdesc;
250 : :
251 : 0 : pdesc = pkg->installed.description;
252 [ # # ]: 0 : if (!pdesc)
253 : 0 : pdesc = pkg->available.description;
254 [ # # ]: 0 : if (!pdesc)
255 : 0 : pdesc = _("(no description available)");
256 : :
257 : 0 : *len = strcspn(pdesc, "\n");
258 : :
259 : 0 : return pdesc;
260 : : }
261 : :
262 : : /**
263 : : * Return a character abbreviated representation of the package want status.
264 : : *
265 : : * @param pkg The package to consider.
266 : : *
267 : : * @return The character abbreviated representation.
268 : : */
269 : : int
270 : 0 : pkg_abbrev_want(const struct pkginfo *pkg)
271 : : {
272 : 0 : return "uihrp"[pkg->want];
273 : : }
274 : :
275 : : /**
276 : : * Return a character abbreviated representation of the package current status.
277 : : *
278 : : * @param pkg The package to consider.
279 : : *
280 : : * @return The character abbreviated representation.
281 : : */
282 : : int
283 : 0 : pkg_abbrev_status(const struct pkginfo *pkg)
284 : : {
285 : 0 : return "ncHUFWti"[pkg->status];
286 : : }
287 : :
288 : : /**
289 : : * Return a character abbreviated representation of the package eflag status.
290 : : *
291 : : * @param pkg The package to consider.
292 : : *
293 : : * @return The character abbreviated representation.
294 : : */
295 : : int
296 : 0 : pkg_abbrev_eflag(const struct pkginfo *pkg)
297 : : {
298 : 0 : return " R"[pkg->eflag];
299 : : }
300 : :
301 : : /**
302 : : * Return a string representation of the package want status name.
303 : : *
304 : : * @param pkg The package to consider.
305 : : *
306 : : * @return The string representation.
307 : : */
308 : : const char *
309 : 0 : pkg_want_name(const struct pkginfo *pkg)
310 : : {
311 : 0 : return wantinfos[pkg->want].name;
312 : : }
313 : :
314 : : /**
315 : : * Return a string representation of the package eflag status name.
316 : : *
317 : : * @param pkg The package to consider.
318 : : *
319 : : * @return The string representation.
320 : : */
321 : : const char *
322 : 0 : pkg_eflag_name(const struct pkginfo *pkg)
323 : : {
324 : 0 : return eflaginfos[pkg->eflag].name;
325 : : }
326 : :
327 : : /**
328 : : * Return a string representation of the package current status name.
329 : : *
330 : : * @param pkg The package to consider.
331 : : *
332 : : * @return The string representation.
333 : : */
334 : : const char *
335 : 0 : pkg_status_name(const struct pkginfo *pkg)
336 : : {
337 : 0 : return statusinfos[pkg->status].name;
338 : : }
339 : :
340 : : /**
341 : : * Return a string representation of the package priority name.
342 : : *
343 : : * @param pkg The package to consider.
344 : : *
345 : : * @return The string representation.
346 : : */
347 : : const char *
348 : 2 : pkg_priority_name(const struct pkginfo *pkg)
349 : : {
350 [ - + ]: 2 : if (pkg->priority == PKG_PRIO_OTHER)
351 : 0 : return pkg->otherpriority;
352 : : else
353 : 2 : return priorityinfos[pkg->priority].name;
354 : : }
355 : :
356 : : /**
357 : : * Compare a package to be sorted by non-ambiguous name and architecture.
358 : : *
359 : : * @param a A pointer of a pointer to a struct pkginfo.
360 : : * @param b A pointer of a pointer to a struct pkginfo.
361 : : *
362 : : * @return An integer with the result of the comparison.
363 : : * @retval -1 a is earlier than b.
364 : : * @retval 0 a is equal to b.
365 : : * @retval 1 a is later than b.
366 : : */
367 : : int
368 : 0 : pkg_sorter_by_nonambig_name_arch(const void *a, const void *b)
369 : : {
370 : 0 : const struct pkginfo *pa = *(const struct pkginfo **)a;
371 : 0 : const struct pkginfo *pb = *(const struct pkginfo **)b;
372 : 0 : const struct pkgbin *pbina = &pa->installed;
373 : 0 : const struct pkgbin *pbinb = &pb->installed;
374 : : int res;
375 : :
376 : 0 : res = strcmp(pa->set->name, pb->set->name);
377 [ # # ]: 0 : if (res)
378 : 0 : return res;
379 : :
380 [ # # ]: 0 : if (pbina->arch == pbinb->arch)
381 : 0 : return 0;
382 : :
383 [ # # ]: 0 : if (pkgbin_name_needs_arch(pbina, pnaw_nonambig)) {
384 [ # # ]: 0 : if (pkgbin_name_needs_arch(pbinb, pnaw_nonambig))
385 : 0 : return strcmp(pbina->arch->name, pbinb->arch->name);
386 : : else
387 : 0 : return 1;
388 : : } else {
389 : 0 : return -1;
390 : : }
391 : : }
392 : :
393 : : /**
394 : : * Add a string representation of the source package version to a varbuf.
395 : : *
396 : : * It parses the Source field (if present), and extracts the optional
397 : : * version enclosed in parenthesis. Otherwise it falls back to use the
398 : : * binary package version. It NUL terminates the varbuf.
399 : : *
400 : : * @param vb The varbuf struct to modify.
401 : : * @param pkg The package to consider.
402 : : * @param pkgbin The binary package instance to consider.
403 : : */
404 : : void
405 : 4 : varbuf_add_source_version(struct varbuf *vb,
406 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin)
407 : : {
408 : 4 : struct dpkg_version version = DPKG_VERSION_INIT;
409 : :
410 : 4 : pkg_source_version(&version, pkg, pkgbin);
411 : 4 : varbufversion(vb, &version, vdew_nonambig);
412 : 4 : }
413 : :
414 : : void
415 : 7 : pkg_source_version(struct dpkg_version *version,
416 : : const struct pkginfo *pkg, const struct pkgbin *pkgbin)
417 : : {
418 : : const char *version_str;
419 : :
420 [ + + ]: 7 : if (pkgbin->source)
421 : 4 : version_str = strchr(pkgbin->source, '(');
422 : : else
423 : 3 : version_str = NULL;
424 : :
425 [ + + ]: 7 : if (version_str == NULL) {
426 : 5 : *version = pkgbin->version;
427 : : } else {
428 : : struct dpkg_error err;
429 : 2 : struct varbuf vb = VARBUF_INIT;
430 : : size_t len;
431 : :
432 : 2 : version_str++;
433 : 2 : len = strcspn(version_str, ")");
434 : 2 : varbuf_add_buf(&vb, version_str, len);
435 : :
436 [ - + ]: 2 : if (parseversion(version, varbuf_str(&vb), &err) < 0)
437 : 0 : ohshit(_("version '%s' has bad syntax: %s"),
438 : : varbuf_str(&vb), err.str);
439 : :
440 : 2 : varbuf_destroy(&vb);
441 : : }
442 : 7 : }
|