diff --git a/Makefile-lib.am b/Makefile-lib.am index 9559e0b9..62052a8d 100644 --- a/Makefile-lib.am +++ b/Makefile-lib.am @@ -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 diff --git a/src/app/rpmostree-builtin-shlib-backend.c b/src/app/rpmostree-builtin-shlib-backend.c index a564eaad..05276f8a 100644 --- a/src/app/rpmostree-builtin-shlib-backend.c +++ b/src/app/rpmostree-builtin-shlib-backend.c @@ -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 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); } diff --git a/src/lib/rpmostree-package.c b/src/lib/rpmostree-package.c index e82e36b1..d9040591 100644 --- a/src/lib/rpmostree-package.c +++ b/src/lib/rpmostree-package.c @@ -30,8 +30,8 @@ #include "config.h" +#include "rpmostree-shlib-ipc-private.h" #include "rpmostree-package-priv.h" -#include "rpmostree-rpm-util.h" #include #include @@ -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) + /* 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 && - 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)); - return FALSE; + 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); diff --git a/src/lib/rpmostree-shlib-ipc-private.h b/src/lib/rpmostree-shlib-ipc-private.h index 8e5a5460..1213246b 100644 --- a/src/lib/rpmostree-shlib-ipc-private.h +++ b/src/lib/rpmostree-shlib-ipc-private.h @@ -20,10 +20,13 @@ #pragma once +#include + 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 diff --git a/src/lib/rpmostree.c b/src/lib/rpmostree.c index 0db953a4..f0383b71 100644 --- a/src/lib/rpmostree.c +++ b/src/lib/rpmostree.c @@ -23,11 +23,12 @@ #include #include #include +#include +#include #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); } diff --git a/src/libpriv/rpmostree-rpm-util.c b/src/libpriv/rpmostree-rpm-util.c index cce9555f..0669a0c8 100644 --- a/src/libpriv/rpmostree-rpm-util.c +++ b/src/libpriv/rpmostree-rpm-util.c @@ -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; } diff --git a/src/libpriv/rpmostree-rpm-util.h b/src/libpriv/rpmostree-rpm-util.h index 84d4b9d0..e9bf4d8a 100644 --- a/src/libpriv/rpmostree-rpm-util.h +++ b/src/libpriv/rpmostree-rpm-util.h @@ -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);