Skip to content

Commit

Permalink
WIP Demo of using cxx-rs
Browse files Browse the repository at this point in the history
  • Loading branch information
cgwalters committed Nov 27, 2020
1 parent f28cd65 commit bd0cd00
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 47 deletions.
11 changes: 11 additions & 0 deletions Makefile-libpriv.am
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ librpmostreepriv_la_CXXFLAGS = $(AM_CXXFLAGS) $(rpmostreepriv_common_cflags)

librpmostreepriv_la_LIBADD = \
$(PKGDEP_RPMOSTREE_LIBS) \
-lstdc++ \
libglnx.la \
$(CAP_LIBS) \
$(NULL)
Expand All @@ -109,3 +110,13 @@ AM_V_GPERF_0 = @echo " GPERF " $@;
src/%.c: src/%.gperf Makefile
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GPERF)$(GPERF) < $< > $@.tmp && mv $@.tmp $@

# Also we now use cxx.rs
rpmostree-cxxrs.h: rust/src/lib.rs
$(AM_V_GEN) cxxbridge rust/src/lib.rs --header > $@
rpmostree-cxxrs.cxx: rust/src/lib.rs
$(AM_V_GEN) cxxbridge rust/src/lib.rs > $@
cxxrs_sources = rpmostree-cxxrs.h rpmostree-cxxrs.cxx
librpmostreepriv_la_SOURCES += $(cxxrs_sources)
BUILT_SOURCES += $(cxxrs_sources)
GITIGNOREFILES += $(cxxrs_sources)
2 changes: 1 addition & 1 deletion Makefile-rpm-ostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ rpm_ostree_SOURCES = src/app/main.c \
src/app/rpmostree-db-builtin-diff.c \
src/app/rpmostree-db-builtin-list.c \
src/app/rpmostree-db-builtin-version.c \
src/app/rpmostree-dbus-helpers.c \
src/app/rpmostree-dbus-helpers.cxx \
src/app/rpmostree-dbus-helpers.h \
src/app/rpmostree-container-builtins.h \
src/app/rpmostree-container-builtins.c \
Expand Down
4 changes: 4 additions & 0 deletions ci/installdeps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ pkg_install ostree{,-devel,-grub2} createrepo_c /usr/bin/jq python3-pyyaml \
libubsan libasan libtsan elfutils fuse sudo python3-gobject-base \
selinux-policy-devel selinux-policy-targeted python3-createrepo_c \
rsync python3-rpm parallel clang rustfmt-preview distribution-gpg-keys

if ! command -v cxxbridge; then
cargo install --root=/usr cxxbridge-cmd
fi
39 changes: 39 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2018"

[dependencies]
anyhow = "1.0.34"
cxx = "1.0"
serde = "1.0.117"
serde_derive = "1.0.117"
serde_json = "1.0.59"
Expand Down
10 changes: 10 additions & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
mod ffiutil;
mod includes;

#[cxx::bridge(namespace = "rpmostreecxx")]
mod ffi {
// utils.rs
extern "Rust" {
fn running_in_nspawn() -> bool;

fn download_to_fd(url: &str) -> Result<i32>;
}
}

mod cliwrap;
pub use cliwrap::*;
mod composepost;
Expand Down
44 changes: 28 additions & 16 deletions rust/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ pub fn varsubst(instr: &str, vars: &HashMap<String, String>) -> Result<String> {
return Ok(s);
}

/* nspawn by default doesn't give us CAP_NET_ADMIN; see
* https://pagure.io/releng/issue/6602#comment-71214
* https://pagure.io/koji/pull-request/344#comment-21060
*
* Theoretically we should do capable(CAP_NET_ADMIN)
* but that's a lot of ugly code, and the only known
* place we hit this right now is nspawn. Plus
* we want to use userns down the line anyways where
* we'll regain CAP_NET_ADMIN.
*/
pub fn running_in_nspawn() -> bool {
use std::os::unix::ffi::OsStrExt;
match std::env::var_os("container") {
Some(c) if c.as_bytes() == b"nspawn" => true,
_ => false,
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -195,6 +213,16 @@ mod tests {
}
}

mod cxxffi {
use super::*;
use std::os::unix::io::IntoRawFd;

pub fn download_to_fd(url: &str) -> Result<i32> {
Ok(download_url_to_tmpfile(url)?.into_raw_fd())
}
}
pub use cxxffi::*;

mod ffi {
use super::*;
use crate::ffiutil::*;
Expand All @@ -203,24 +231,8 @@ mod ffi {
use glib_sys;
use libc;
use std::ffi::CString;
use std::os::unix::io::IntoRawFd;
use std::ptr;

#[no_mangle]
pub extern "C" fn ror_download_to_fd(
url: *const libc::c_char,
gerror: *mut *mut glib_sys::GError,
) -> libc::c_int {
let url: Borrowed<glib::GString> = unsafe { from_glib_borrow(url) };
match download_url_to_tmpfile(url.as_str()) {
Ok(f) => f.into_raw_fd(),
Err(e) => {
error_to_glib(&e, gerror);
-1
}
}
}

#[no_mangle]
pub extern "C" fn ror_util_varsubst(
s: *const libc::c_char,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "rpmostree-util.h"
#include "rpmostree-rpm-util.h"
#include "rpmostree-rust.h"
#include "rpmostree-cxxrs.h"

#define RPMOSTREE_CLI_ID "cli"

Expand Down Expand Up @@ -586,7 +587,7 @@ on_owner_changed (GObject *object,
/* Owner shouldn't change during a transaction
* that messes with notifications, abort, abort.
*/
TransactionProgress *tp = user_data;
auto tp = static_cast<TransactionProgress *>(user_data);
tp->error = g_dbus_error_new_for_dbus_error ("org.projectatomic.rpmostreed.Error.Failed",
"Bus owner changed, aborting. This likely "
"means the daemon crashed; check logs with "
Expand All @@ -598,14 +599,14 @@ static void
cancelled_handler (GCancellable *cancellable,
gpointer user_data)
{
RPMOSTreeTransaction *transaction = user_data;
auto transaction = static_cast<RPMOSTreeTransaction*>(user_data);
rpmostree_transaction_call_cancel_sync (transaction, NULL, NULL);
}

static gboolean
on_sigint (gpointer user_data)
{
GCancellable *cancellable = user_data;
auto cancellable = static_cast<GCancellable*>(user_data);
if (!g_cancellable_is_cancelled (cancellable))
{
g_printerr ("Caught SIGINT, cancelling transaction\n");
Expand Down Expand Up @@ -1035,7 +1036,7 @@ rpmostree_print_package_diffs (GVariant *variant)

while (!g_queue_is_empty (&queue))
{
child = g_queue_pop_head (&queue);
child = (GVariant*)g_queue_pop_head (&queue);
pkg_diff_variant_print (child);
g_variant_unref (child);
}
Expand All @@ -1061,12 +1062,13 @@ rpmostree_sort_pkgs_strv (const char *const* pkgs,
g_str_has_prefix (*pkg, "https://"))
{
g_print ("Downloading '%s'... ", *pkg);
glnx_autofd int fd = ror_download_to_fd (*pkg, error);
if (fd < 0)
{
g_print ("failed!\n");
return FALSE;
}
glnx_autofd int fd = -1;
try {
fd = rpmostreecxx::download_to_fd(*pkg);
} catch (std::exception& e) {
g_print ("failed!\n");
return glnx_throw (error, "%s", e.what());
}
g_print ("done!\n");

int idx = g_unix_fd_list_append (fd_list, fd, error);
Expand All @@ -1092,7 +1094,7 @@ rpmostree_sort_pkgs_strv (const char *const* pkgs,
}

*out_fd_idxs = g_variant_ref_sink (g_variant_new ("ah", &builder));
*out_repo_pkgs = g_steal_pointer (&repo_pkgs);
*out_repo_pkgs = (GPtrArray*)g_steal_pointer (&repo_pkgs);
return TRUE;
}

Expand Down Expand Up @@ -1188,7 +1190,7 @@ get_modifiers_variant (const char *set_refspec,
g_variant_dict_insert (&dict, "ex-local-repo-remote", "h", idx);
}

*out_fd_list = g_steal_pointer (&fd_list);
*out_fd_list = (GUnixFDList*)g_steal_pointer (&fd_list);
*out_modifiers = g_variant_ref_sink (g_variant_dict_end (&dict));
return TRUE;
}
Expand Down Expand Up @@ -1357,7 +1359,7 @@ print_advisories (GVariant *advisories,

for (guint i = 0; i < sec_advisories->len; i++)
{
GVariant *advisory = sec_advisories->pdata[i];
auto advisory = static_cast<GVariant*>(sec_advisories->pdata[i]);

const char *id;
g_variant_get_child (advisory, 0, "&s", &id);
Expand Down
19 changes: 2 additions & 17 deletions src/libpriv/rpmostree-bwrap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

#include "config.h"
#include "rpmostree-cxxrs.h"
#include "rpmostree-bwrap.h"

#include <err.h>
Expand Down Expand Up @@ -237,22 +238,6 @@ teardown_rofiles (GLnxTmpDir *mnt_tmp)
sd_journal_print (LOG_WARNING, "%s", tmp_error->message);
}

/* nspawn by default doesn't give us CAP_NET_ADMIN; see
* https://pagure.io/releng/issue/6602#comment-71214
* https://pagure.io/koji/pull-request/344#comment-21060
*
* Theoretically we should do capable(CAP_NET_ADMIN)
* but that's a lot of ugly code, and the only known
* place we hit this right now is nspawn. Plus
* we want to use userns down the line anyways where
* we'll regain CAP_NET_ADMIN.
*/
static gboolean
running_in_nspawn (void)
{
return g_strcmp0 (getenv ("container"), "systemd-nspawn") == 0;
}

RpmOstreeBwrap *
rpmostree_bwrap_new_base (int rootfs_fd, GError **error)
{
Expand Down Expand Up @@ -302,7 +287,7 @@ rpmostree_bwrap_new_base (int rootfs_fd, GError **error)
"--unshare-cgroup-try",
NULL);

if (!running_in_nspawn ())
if (!rpmostreecxx::running_in_nspawn ())
rpmostree_bwrap_append_bwrap_argv (ret, "--unshare-net", NULL);

/* Capabilities; this is a subset of the Docker (1.13 at least) default.
Expand Down

0 comments on commit bd0cd00

Please sign in to comment.