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