summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dpkg/dpkg-db.h21
-rw-r--r--lib/dpkg/libdpkg.map3
-rw-r--r--lib/dpkg/pkg-show.c101
-rw-r--r--lib/dpkg/pkg.c1
4 files changed, 126 insertions, 0 deletions
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index ba8fbd9..a22cac6 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -118,6 +118,9 @@ struct pkgbin {
multiarch_foreign,
} multiarch;
const struct dpkg_arch *arch;
+ /* The following is the "pkgname:archqual" cached string, if this was a
+ * C++ class this member would be mutable. */
+ const char *pkgname_archqual;
const char *description;
const char *maintainer;
const char *source;
@@ -329,6 +332,24 @@ int parseversion(struct versionrevision *rversion, const char *,
const char *versiondescribe(const struct versionrevision*,
enum versiondisplayepochwhen);
+enum pkg_name_arch_when {
+ /* Never display arch. */
+ pnaw_never,
+ /* Display arch only when it's non-ambiguous. */
+ pnaw_nonambig,
+ /* Display arch only when it's a foreign one. */
+ pnaw_foreign,
+ /* Always display arch. */
+ pnaw_always,
+};
+
+void varbuf_add_pkgbin_name(struct varbuf *vb, const struct pkginfo *pkg,
+ const struct pkgbin *pkgbin,
+ enum pkg_name_arch_when pnaw);
+const char *pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
+ enum pkg_name_arch_when pnaw);
+const char *pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw);
+
/*** from dump.c ***/
void writerecord(FILE*, const char*,
diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map
index 9f80069..0bdc9f3 100644
--- a/lib/dpkg/libdpkg.map
+++ b/lib/dpkg/libdpkg.map
@@ -203,6 +203,9 @@ LIBDPKG_PRIVATE {
pkg_is_informative;
copy_dependency_links;
pkg_sorter_by_name;
+ varbuf_add_pkgbin_name;
+ pkgbin_name;
+ pkg_name;
pkg_summary;
pkg_abbrev_want;
pkg_abbrev_status;
diff --git a/lib/dpkg/pkg-show.c b/lib/dpkg/pkg-show.c
index a8a3b81..d9c4778 100644
--- a/lib/dpkg/pkg-show.c
+++ b/lib/dpkg/pkg-show.c
@@ -29,6 +29,107 @@
#include <dpkg/dpkg-db.h>
#include <dpkg/pkg-show.h>
+static bool
+pkgbin_name_needs_arch(const struct pkgbin *pkgbin,
+ enum pkg_name_arch_when pnaw)
+{
+ switch (pnaw) {
+ case pnaw_never:
+ break;
+ case pnaw_foreign:
+ if (pkgbin->arch->type == arch_native ||
+ pkgbin->arch->type == arch_all ||
+ pkgbin->arch->type == arch_none)
+ break;
+ return true;
+ case pnaw_nonambig:
+ if (pkgbin->multiarch != multiarch_same)
+ break;
+ /* Fall through. */
+ case pnaw_always:
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Add a string representation of the package name to a varbuf.
+ *
+ * Works exactly like pkgbin_name() but acts on the varbuf instead of
+ * returning a string. It NUL terminates the varbuf.
+ *
+ * @param vb The varbuf struct to modify.
+ * @param pkg The package to consider.
+ * @param pkgbin The binary package instance to consider.
+ * @param pnaw When to display the architecture qualifier.
+ */
+void
+varbuf_add_pkgbin_name(struct varbuf *vb,
+ const struct pkginfo *pkg, const struct pkgbin *pkgbin,
+ enum pkg_name_arch_when pnaw)
+{
+ varbuf_add_str(vb, pkg->set->name);
+ if (pkgbin_name_needs_arch(pkgbin, pnaw))
+ varbuf_add_archqual(vb, pkgbin->arch);
+ varbuf_end_str(vb);
+}
+
+/**
+ * Return a string representation of the package name.
+ *
+ * The returned string must not be freed, and it's permanently allocated so
+ * can be used as long as the non-freeing memory pool has not been freed.
+ *
+ * The pnaw parameter should be one of pnaw_never (never print arch),
+ * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
+ * arch for non ambiguous cases) or pnaw_always (always print arch),
+ *
+ * @param pkg The package to consider.
+ * @param pkgbin The binary package instance to consider.
+ * @param pnaw When to display the architecture qualifier.
+ *
+ * @return The string representation.
+ */
+const char *
+pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
+ enum pkg_name_arch_when pnaw)
+{
+ if (!pkgbin_name_needs_arch(pkgbin, pnaw))
+ return pkg->set->name;
+
+ /* Cache the package name representation, for later reuse. */
+ if (pkgbin->pkgname_archqual == NULL) {
+ struct varbuf vb = VARBUF_INIT;
+
+ varbuf_add_str(&vb, pkg->set->name);
+ varbuf_add_archqual(&vb, pkgbin->arch);
+ varbuf_end_str(&vb);
+
+ pkgbin->pkgname_archqual = nfstrsave(vb.buf);
+
+ varbuf_destroy(&vb);
+ }
+
+ return pkgbin->pkgname_archqual;
+}
+
+/**
+ * Return a string representation of the package name.
+ *
+ * This is equivalent to pkgbin_name() but just for its installed pkgbin.
+ *
+ * @param pkg The package to consider.
+ * @param pnaw When to display the architecture qualifier.
+ *
+ * @return The string representation.
+ */
+const char *
+pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
+{
+ return pkgbin_name(pkg, &pkg->installed, pnaw);
+}
+
const char *
pkg_summary(const struct pkginfo *pkg, int *len_ret)
{
diff --git a/lib/dpkg/pkg.c b/lib/dpkg/pkg.c
index f554653..51a2ee8 100644
--- a/lib/dpkg/pkg.c
+++ b/lib/dpkg/pkg.c
@@ -33,6 +33,7 @@ pkgbin_blank(struct pkgbin *pkgbin)
pkgbin->essential = false;
pkgbin->multiarch = multiarch_no;
pkgbin->depends = NULL;
+ pkgbin->pkgname_archqual = NULL;
pkgbin->description = NULL;
pkgbin->maintainer = NULL;
pkgbin->source = NULL;