lib: Drop dependencies on internal librpmostree-priv

A long time ago now we started injecting the package list
into the ostree commit.
We were carrying backwards compatibility code to do a checkout
of an ostree commit and extract it, but if we delete that
and have it return an error, it removes the last bits
that end up calling into our internal librpmostreepriv.la.

Now the internal shared library only links to our private `libdnf.so.2`,
`libglnx.la` statically, and libglib.so and libostree.so.

In the future it'd be nice to even drop the linkage to `libdnf.so.2`
because that drags in a lot of stuff, and I suspect e.g. gnome-software
may hit incompatibilities if it also links in the "system" libdnf.
This commit is contained in:
Colin Walters 2020-12-16 20:26:03 +00:00 committed by OpenShift Merge Robot
parent 1de524f668
commit 3e025d9b92
7 changed files with 96 additions and 86 deletions

View File

@ -34,7 +34,8 @@ librpmostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libp
-fvisibility=hidden '-D_RPMOSTREE_EXTERN=__attribute((visibility("default"))) extern' \
$(PKGDEP_RPMOSTREE_CFLAGS)
librpmostree_1_la_LDFLAGS = $(AM_LDFLAGS) -version-number 1:0:0 -Bsymbolic-functions
librpmostree_1_la_LIBADD = $(PKGDEP_RPMOSTREE_LIBS) librpmostreepriv.la $(librpmostree_rust_path)
librpmostree_1_la_LIBADD = $(PKGDEP_RPMOSTREE_LIBS) libglnx.la
EXTRA_librpmostree_1_la_DEPENDENCIES = libdnf.so.2
# The g-ir-scanner creates a stub executable (to help introspect type information) which
# links to our stuff. We want to make sure it picks up our fresh libdnf and not a possibly

View File

@ -32,6 +32,7 @@
#include "rpmostree-builtins.h"
#include "rpmostree-libbuiltin.h"
#include "rpmostree-rust.h"
#include "rpmostree-rpm-util.h"
#include "rpmostree.h"
#include "rpmostree-core.h"
#include "src/lib/rpmostree-shlib-ipc-private.h"
@ -39,14 +40,12 @@
#include <libglnx.h>
static gboolean
send_memfd_result (int ret_memfd, GError **error)
send_memfd_result (GSocket *ipc_sock, int ret_memfd, GError **error)
{
int fdarray[] = {ret_memfd, -1 };
g_autoptr(GUnixFDList) list = g_unix_fd_list_new_from_array (fdarray, 1);
g_autoptr(GUnixFDMessage) message = G_UNIX_FD_MESSAGE (g_unix_fd_message_new_with_fd_list (list));
g_autoptr(GSocket) ipc_sock = g_socket_new_from_fd (RPMOSTREE_SHLIB_IPC_FD, error);
if (!ipc_sock)
return FALSE;
GOutputVector ov;
char buffer[1];
buffer[0] = 0xFF;
@ -62,6 +61,24 @@ send_memfd_result (int ret_memfd, GError **error)
return TRUE;
}
static GVariant *
impl_packagelist_from_commit (OstreeRepo *repo, const char *commit, GError **error)
{
g_autoptr(GError) local_error = NULL;
g_autoptr(RpmOstreeRefSack) rsack =
rpmostree_get_refsack_for_commit (repo, commit, NULL, &local_error);
if (!rsack)
{
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return g_variant_new_maybe ((GVariantType*) RPMOSTREE_SHLIB_IPC_PKGLIST, NULL);
g_propagate_error (error, g_steal_pointer (&local_error));
return NULL;
}
g_autoptr(GVariant) pkgs = rpmostree_variant_pkgs_from_sack (rsack);
return g_variant_ref_sink (g_variant_new_maybe ((GVariantType*) RPMOSTREE_SHLIB_IPC_PKGLIST, pkgs));
}
gboolean
rpmostree_builtin_shlib_backend (int argc,
char **argv,
@ -74,6 +91,10 @@ rpmostree_builtin_shlib_backend (int argc,
const char *arg = argv[1];
g_autoptr(GSocket) ipc_sock = g_socket_new_from_fd (RPMOSTREE_SHLIB_IPC_FD, error);
if (!ipc_sock)
return FALSE;
g_autoptr(GVariant) ret = NULL;
if (g_str_equal (arg, "get-basearch"))
@ -91,6 +112,16 @@ rpmostree_builtin_shlib_backend (int argc,
return FALSE;
ret = g_variant_new_string (rets);
}
else if (g_str_equal (arg, "packagelist-from-commit"))
{
OstreeRepo *repo = ostree_repo_open_at (AT_FDCWD, ".", NULL, error);
if (!repo)
return FALSE;
const char *commit = argv[2];
ret = impl_packagelist_from_commit (repo, commit, error);
if (!ret)
return FALSE;
}
else
return glnx_throw (error, "unknown shlib-backend %s", arg);
@ -103,5 +134,5 @@ rpmostree_builtin_shlib_backend (int argc,
if (fcntl (ret_memfd, F_ADD_SEALS, seals) == -1)
return glnx_throw_errno_prefix (error, "fcntl(sealing)");
return send_memfd_result (glnx_steal_fd (&ret_memfd), error);
return send_memfd_result (ipc_sock, glnx_steal_fd (&ret_memfd), error);
}

View File

@ -30,8 +30,8 @@
#include "config.h"
#include "rpmostree-shlib-ipc-private.h"
#include "rpmostree-package-priv.h"
#include "rpmostree-rpm-util.h"
#include <string.h>
#include <stdlib.h>
@ -44,10 +44,6 @@ typedef GObjectClass RpmOstreePackageClass;
struct RpmOstreePackage
{
GObject parent_instance;
/* libdnf-based pkg */
RpmOstreeRefSack *sack;
DnfPackage *hypkg;
/* gvariant-based pkg */
GVariant *gv_nevra;
/* deconstructed/cached values */
char *nevra;
@ -63,8 +59,6 @@ static void
rpm_ostree_package_finalize (GObject *object)
{
RpmOstreePackage *pkg = (RpmOstreePackage*)object;
g_clear_pointer (&pkg->hypkg, g_object_unref);
g_clear_pointer (&pkg->sack, rpmostree_refsack_unref);
g_clear_pointer (&pkg->gv_nevra, g_variant_unref);
g_clear_pointer (&pkg->nevra, g_free);
@ -150,9 +144,6 @@ rpm_ostree_package_get_arch (RpmOstreePackage *p)
int
rpm_ostree_package_cmp (RpmOstreePackage *p1, RpmOstreePackage *p2)
{
if (p1->hypkg && p2->hypkg)
return dnf_package_cmp (p1->hypkg, p2->hypkg);
int ret = strcmp (p1->name, p2->name);
if (ret)
return ret;
@ -169,25 +160,6 @@ rpm_ostree_package_cmp (RpmOstreePackage *p1, RpmOstreePackage *p2)
return strcmp (p1->arch, p2->arch);
}
RpmOstreePackage *
_rpm_ostree_package_new (RpmOstreeRefSack *rsack, DnfPackage *hypkg)
{
RpmOstreePackage *p = g_object_new (RPM_OSTREE_TYPE_PACKAGE, NULL);
/* We do internal refcounting of the sack because hawkey doesn't */
p->sack = rpmostree_refsack_ref (rsack);
p->hypkg = g_object_ref (hypkg);
/* we deconstruct now to make accessors simpler */
/* cache nevra internally because we can't rely on libsolv
* https://github.com/rpm-software-management/libdnf/pull/388 */
p->nevra = g_strdup (dnf_package_get_nevra (p->hypkg));
p->name = dnf_package_get_name (p->hypkg);
p->evr = dnf_package_get_evr (p->hypkg);
p->arch = dnf_package_get_arch (p->hypkg);
return p;
}
RpmOstreePackage*
_rpm_ostree_package_new_from_variant (GVariant *gv_nevra)
{
@ -220,22 +192,6 @@ get_commit_rpmdb_pkglist (GVariant *commit)
G_VARIANT_TYPE ("a(sssss)"));
}
static GPtrArray *
query_all_packages_in_sack (RpmOstreeRefSack *rsack)
{
g_autoptr(GPtrArray) result = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GPtrArray) pkglist = rpmostree_sack_get_sorted_packages (rsack->sack);
const guint c = pkglist->len;
for (guint i = 0; i < c; i++)
{
DnfPackage *pkg = pkglist->pdata[i];
g_ptr_array_add (result, _rpm_ostree_package_new (rsack, pkg));
}
return g_steal_pointer (&result);
}
/* Opportunistically try to use the new rpmostree.rpmdb.pkglist metadata, otherwise fall
* back to commit rpmdb if available.
*
@ -258,29 +214,36 @@ _rpm_ostree_package_list_for_commit (OstreeRepo *repo,
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, &commit, error))
return FALSE;
/* We used to have a fallback here to checking out the rpmdb from the commit,
* but that currently drags in our internal Rust code which bloats this
* shared library and causes other problems since the main executable
* wants to link to this shared library too. So for now if we don't
* find the pkglist in the commit metadata, just return as if it's
* empty.
*
* TODO: Rework this to run via the special shlib-ipc that is used
* in rpmostree.c.
*/
g_autoptr(GVariant) pkglist_v = get_commit_rpmdb_pkglist (commit);
if (!pkglist_v)
{
/* file-based rpmdb fallback; let fail if rpmdb not available */
g_autoptr(GError) local_error = NULL;
g_autoptr(RpmOstreeRefSack) rsack =
rpmostree_get_refsack_for_commit (repo, rev, cancellable, &local_error);
if (!rsack)
{
if (allow_noent &&
g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
*out_pkglist = NULL;
return TRUE; /* NB: early return */
}
g_propagate_error (error, g_steal_pointer (&local_error));
/* Yeah we could extend the IPC to support sending a fd too but for
* now communicating via the working directory is easier.
*/
int fd = ostree_repo_get_dfd (repo);
g_autofree char *fdpath = g_strdup_printf ("/proc/self/fd/%d", fd);
char *args[] = { "packagelist-from-commit", (char*)rev, NULL };
g_autoptr(GVariant) maybe_pkglist_v = _rpmostree_shlib_ipc_send ("m" RPMOSTREE_SHLIB_IPC_PKGLIST, args, fdpath, error);
if (!maybe_pkglist_v)
return FALSE;
pkglist_v = g_variant_get_maybe (maybe_pkglist_v);
if (!pkglist_v)
{
if (!allow_noent)
return glnx_throw (error, "No package database found");
*out_pkglist = NULL;
return TRUE; /* Note early return */
}
/* Note early return */
*out_pkglist = query_all_packages_in_sack (rsack);
return TRUE;
}
g_autoptr(GPtrArray) pkglist = g_ptr_array_new_with_free_func (g_object_unref);

View File

@ -20,10 +20,13 @@
#pragma once
#include <gio/gio.h>
G_BEGIN_DECLS
#define RPMOSTREE_SHLIB_IPC_FD 3
#define RPMOSTREE_SHLIB_IPC_PKGLIST "a(sssss)"
GVariant *_rpmostree_shlib_ipc_send (const char *variant_type, char **args, GError **error);
GVariant *_rpmostree_shlib_ipc_send (const char *variant_type, char **args, const char *wd, GError **error);
G_END_DECLS

View File

@ -23,11 +23,12 @@
#include <gio/gio.h>
#include <gio/gunixfdmessage.h>
#include <gio/gunixsocketaddress.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "string.h"
#include "libglnx.h"
#include "rpmostree.h"
#include "rpmostree-core.h"
#include "rpmostree-util.h"
#include "rpmostree-shlib-ipc-private.h"
/**
@ -41,7 +42,7 @@
#define IPC_FD 3
GVariant *
_rpmostree_shlib_ipc_send (const char *variant_type, char **args, GError **error)
_rpmostree_shlib_ipc_send (const char *variant_type, char **args, const char *wd, GError **error)
{
g_autoptr(GSubprocessLauncher) launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_PIPE);
int pair[2];
@ -50,6 +51,9 @@ _rpmostree_shlib_ipc_send (const char *variant_type, char **args, GError **error
glnx_fd_close int my_sock_fd = glnx_steal_fd (&pair[0]);
g_subprocess_launcher_take_fd (launcher, pair[1], IPC_FD);
if (wd != NULL)
g_subprocess_launcher_set_cwd (launcher, wd);
g_autoptr(GSocket) my_sock = g_socket_new_from_fd (my_sock_fd, error);
if (!my_sock)
return NULL;
@ -112,7 +116,7 @@ rpm_ostree_get_basearch (void)
{
g_autoptr(GError) local_error = NULL;
char *args[] = { "get-basearch", NULL };
g_autoptr(GVariant) ret = _rpmostree_shlib_ipc_send ("s", args, &local_error);
g_autoptr(GVariant) ret = _rpmostree_shlib_ipc_send ("s", args, NULL, &local_error);
g_assert_no_error (local_error);
return g_variant_dup_string (ret, NULL);
}
@ -129,7 +133,7 @@ rpm_ostree_varsubst_basearch (const char *src, GError **error)
{
g_autoptr(GError) local_error = NULL;
char *args[] = { "varsubst-basearch", (char*)src, NULL };
g_autoptr(GVariant) ret = _rpmostree_shlib_ipc_send ("s", args, &local_error);
g_autoptr(GVariant) ret = _rpmostree_shlib_ipc_send ("s", args, NULL, &local_error);
g_assert_no_error (local_error);
return g_variant_dup_string (ret, NULL);
}

View File

@ -1221,17 +1221,9 @@ rpmostree_sack_get_sorted_packages (DnfSack *sack)
return g_steal_pointer (&pkglist);
}
gboolean
rpmostree_create_rpmdb_pkglist_variant (int dfd,
const char *path,
GVariant **out_variant,
GCancellable *cancellable,
GError **error)
GVariant *
rpmostree_variant_pkgs_from_sack (RpmOstreeRefSack *refsack)
{
g_autoptr(RpmOstreeRefSack) refsack = rpmostree_get_refsack_for_root (dfd, path, error);
if (!refsack)
return FALSE;
/* we insert it sorted here so it can efficiently be searched on retrieval */
g_autoptr(GPtrArray) pkglist = rpmostree_sack_get_sorted_packages (refsack->sack);
@ -1253,7 +1245,21 @@ rpmostree_create_rpmdb_pkglist_variant (int dfd,
dnf_package_get_arch (pkg));
}
*out_variant = g_variant_ref_sink (g_variant_builder_end (&pkglist_v_builder));
return g_variant_ref_sink (g_variant_builder_end (&pkglist_v_builder));
}
gboolean
rpmostree_create_rpmdb_pkglist_variant (int dfd,
const char *path,
GVariant **out_variant,
GCancellable *cancellable,
GError **error)
{
g_autoptr(RpmOstreeRefSack) refsack = rpmostree_get_refsack_for_root (dfd, path, error);
if (!refsack)
return FALSE;
*out_variant = rpmostree_variant_pkgs_from_sack (refsack);
return TRUE;
}

View File

@ -127,6 +127,8 @@ rpmostree_get_refts_for_commit (OstreeRepo *repo,
GCancellable *cancellable,
GError **error);
GVariant *rpmostree_variant_pkgs_from_sack (RpmOstreeRefSack *sack);
gint
rpmostree_pkg_array_compare (DnfPackage **p_pkg1,
DnfPackage **p_pkg2);