From 2129e1da784d3c4f367406b342e8ef0f2784b4ca Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Thu, 29 Oct 2020 10:24:41 +0000 Subject: [PATCH] daemon/syscore: push livefs introspection to Rust This starts bridging parts of the daemon syscore logic to Rust plumbing, moving the livefs detection logic over there as a first consumer. That was the simplest logic available for wiring, and mostly meant as a sanity check. --- rust/cbindgen.toml | 6 ++- rust/src/includes.rs | 30 ++++++++++++ rust/src/lib.rs | 15 +++--- rust/src/lockfile.rs | 22 ++------- rust/src/syscore.rs | 73 ++++++++++++++++++++++++++++ src/daemon/rpmostree-sysroot-core.c | 9 ++-- src/libpriv/rpmostree-origin.h | 2 + src/libpriv/rpmostree-rpm-util.h | 3 +- src/libpriv/rpmostree-rust-prelude.h | 4 ++ 9 files changed, 132 insertions(+), 32 deletions(-) create mode 100644 rust/src/includes.rs create mode 100644 rust/src/syscore.rs diff --git a/rust/cbindgen.toml b/rust/cbindgen.toml index c58cd4d68e..41f588c6b8 100644 --- a/rust/cbindgen.toml +++ b/rust/cbindgen.toml @@ -9,9 +9,11 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(RORHistoryEntry, ror_history_entry_clear) [export] prefix = "ROR" -# Here we exclude functions belonging to the C side which we use on the Rust side and so +# Here we exclude entries belonging to the C side which we use on the Rust side and so # doesn't make sense to re-export. -exclude = ["rpmostree_get_repodata_chksum_repr"] +exclude = ["RpmOstreeOrigin", + "rpmostree_get_repodata_chksum_repr", + "rpmostree_origin_get_live_state" ] [parse] # We don't want cbindgen to parse libdnf-sys, since we're clients of the library, not diff --git a/rust/src/includes.rs b/rust/src/includes.rs new file mode 100644 index 0000000000..a96c87c526 --- /dev/null +++ b/rust/src/includes.rs @@ -0,0 +1,30 @@ +/*! +Helper C functions from rpm-ostree. + +These are prime candidates for oxidation (e.g. to make interacting with +strings more efficient). + +NOTICE: The C header definitions are canonical, please update those first +then synchronize the entries here. +!*/ + +use crate::syscore::ffi::RpmOstreeOrigin; +use libdnf_sys::DnfPackage; + +// From `libpriv/rpmostree-rpm-util.h`. +extern "C" { + pub(crate) fn rpmostree_get_repodata_chksum_repr( + package: *mut DnfPackage, + chksum: *mut *mut libc::c_char, + gerror: *mut *mut glib_sys::GError, + ) -> libc::c_int; +} + +// From `libpriv/rpmostree-origin.h`. +extern "C" { + pub(crate) fn rpmostree_origin_get_live_state( + origin: *mut RpmOstreeOrigin, + out_inprogress: *mut *mut libc::c_char, + out_livereplaced: *mut *mut libc::c_char, + ); +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index ae4d172356..5a6f75345d 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -6,24 +6,27 @@ // pub(crate) utilities mod ffiutil; +mod includes; mod cliwrap; pub use cliwrap::*; mod composepost; pub use self::composepost::*; -mod history; -pub use self::history::*; mod coreos_rootfs; pub use self::coreos_rootfs::*; +mod history; +pub use self::history::*; mod journal; pub use self::journal::*; +mod lockfile; +pub use self::lockfile::*; mod progress; pub use self::progress::*; +mod syscore; +pub use self::syscore::ffi::*; +mod testutils; +pub use self::testutils::*; mod treefile; pub use self::treefile::*; -mod lockfile; -pub use self::lockfile::*; mod utils; pub use self::utils::*; -mod testutils; -pub use self::testutils::*; diff --git a/rust/src/lockfile.rs b/rust/src/lockfile.rs index e98a52f172..608ba82fb3 100644 --- a/rust/src/lockfile.rs +++ b/rust/src/lockfile.rs @@ -7,6 +7,8 @@ /* Copied and adapted from: treefile.rs */ +pub use self::ffi::*; +use crate::utils; use anyhow::Result; use chrono::prelude::*; use openat_ext::OpenatDirExt; @@ -18,8 +20,6 @@ use std::io; use std::iter::Extend; use std::path::Path; -use crate::utils; - /// Given a lockfile filename, parse it fn lockfile_parse>(filename: P) -> Result { let filename = filename.as_ref(); @@ -191,13 +191,13 @@ mod tests { mod ffi { use super::*; + use crate::ffiutil::*; + use crate::includes::*; use glib::translate::*; use glib_sys; use libc; - use std::ptr; - - use crate::ffiutil::*; use libdnf_sys::*; + use std::ptr; #[no_mangle] pub extern "C" fn ror_lockfile_read( @@ -304,16 +304,4 @@ mod ffi { gerror, ) } - - /* Some helper rpm-ostree C functions to deal with libdnf stuff. These are prime candidates for - * oxidation since it makes e.g. interacting with strings less efficient. */ - extern "C" { - pub(crate) fn rpmostree_get_repodata_chksum_repr( - package: *mut DnfPackage, - chksum: *mut *mut libc::c_char, - gerror: *mut *mut glib_sys::GError, - ) -> libc::c_int; - } } - -pub use self::ffi::*; diff --git a/rust/src/syscore.rs b/rust/src/syscore.rs new file mode 100644 index 0000000000..b896782729 --- /dev/null +++ b/rust/src/syscore.rs @@ -0,0 +1,73 @@ +use self::ffi::RpmOstreeOrigin; +use std::ptr::NonNull; + +/// Reference to an `RpmOstreeOrigin`. +#[derive(Debug)] +pub(crate) struct OriginRef { + origin: NonNull, +} + +impl OriginRef { + /// Build a reference object from a C pointer. + fn from_ffi_ptr(oref: *mut RpmOstreeOrigin) -> Self { + Self { + origin: NonNull::new(oref).expect("NULL RpmOstreeOrigin"), + } + } + + /// Get `livefs` details for this deployment origin. + pub(crate) fn get_live_state<'o>(&'o self) -> OriginLiveState<'o> { + use crate::includes::rpmostree_origin_get_live_state; + use glib::translate::from_glib_full; + + let mut out_inprogress: *mut libc::c_char = std::ptr::null_mut(); + let mut out_livereplaced: *mut libc::c_char = std::ptr::null_mut(); + unsafe { + rpmostree_origin_get_live_state( + self.origin.as_ptr(), + &mut out_inprogress, + &mut out_livereplaced, + ); + }; + let in_progress = unsafe { from_glib_full(out_inprogress) }; + let replaced = unsafe { from_glib_full(out_livereplaced) }; + + OriginLiveState { + _origin: self, + in_progress, + replaced, + } + } +} + +/// `livefs` state and details for a given deployment origin. +#[derive(Debug)] +pub(crate) struct OriginLiveState<'o> { + /// Underlying deployment origin. + _origin: &'o OriginRef, + /// Checksum for the in-progress livefs. + pub in_progress: Option, + /// Checksum for the underlying replaced commit. + pub replaced: Option, +} + +impl<'o> OriginLiveState<'o> { + /// Return whether the given deployment is live-modified. + pub(crate) fn is_live(self) -> bool { + self.in_progress.is_some() || self.replaced.is_some() + } +} + +pub mod ffi { + use super::OriginRef; + + /// Opaque type for C interop: RpmOstreeOrigin. + pub enum RpmOstreeOrigin {} + + #[no_mangle] + pub extern "C" fn ror_origin_is_live(origin_ptr: *mut RpmOstreeOrigin) -> libc::c_int { + let origin = OriginRef::from_ffi_ptr(origin_ptr); + let livestate = origin.get_live_state(); + livestate.is_live().into() + } +} diff --git a/src/daemon/rpmostree-sysroot-core.c b/src/daemon/rpmostree-sysroot-core.c index d08a90d633..cd8bb41d37 100644 --- a/src/daemon/rpmostree-sysroot-core.c +++ b/src/daemon/rpmostree-sysroot-core.c @@ -486,13 +486,10 @@ rpmostree_syscore_deployment_is_live (OstreeDeployment *deployment, gboolean *out_is_live, GError **error) { - g_autofree char *inprogress_checksum = NULL; - g_autofree char *livereplaced_checksum = NULL; - - if (!rpmostree_syscore_deployment_get_live (deployment, &inprogress_checksum, - &livereplaced_checksum, error)) + g_autoptr(RpmOstreeOrigin) origin = rpmostree_origin_parse_deployment (deployment, error); + if (!origin) return FALSE; - *out_is_live = (inprogress_checksum != NULL || livereplaced_checksum != NULL); + *out_is_live = ror_origin_is_live(origin); return TRUE; } diff --git a/src/libpriv/rpmostree-origin.h b/src/libpriv/rpmostree-origin.h index 0513dd7ed9..86260f60e4 100644 --- a/src/libpriv/rpmostree-origin.h +++ b/src/libpriv/rpmostree-origin.h @@ -107,6 +107,8 @@ rpmostree_origin_get_unconfigured_state (RpmOstreeOrigin *origin); gboolean rpmostree_origin_may_require_local_assembly (RpmOstreeOrigin *origin); +// WARNING: This prototype is also redefined in Rust, if changing this +// please also update `includes.rs`. void rpmostree_origin_get_live_state (RpmOstreeOrigin *origin, char **out_inprogress, diff --git a/src/libpriv/rpmostree-rpm-util.h b/src/libpriv/rpmostree-rpm-util.h index 0d3f474e31..bc8ef42ae0 100644 --- a/src/libpriv/rpmostree-rpm-util.h +++ b/src/libpriv/rpmostree-rpm-util.h @@ -178,7 +178,8 @@ rpmostree_custom_nevra_strdup (const char *name, char * rpmostree_header_custom_nevra_strdup (Header h, RpmOstreePkgNevraFlags flags); -/* NB: this function is exposed to Rust */ +// WARNING: This prototype is also redefined in Rust, if changing this +// please also update `includes.rs`. gboolean rpmostree_get_repodata_chksum_repr (DnfPackage *pkg, char **out_chksum_repr, diff --git a/src/libpriv/rpmostree-rust-prelude.h b/src/libpriv/rpmostree-rust-prelude.h index a8c189a40d..1302e2bde5 100644 --- a/src/libpriv/rpmostree-rust-prelude.h +++ b/src/libpriv/rpmostree-rust-prelude.h @@ -22,6 +22,9 @@ #include +/* Forward declarations */ +typedef struct RpmOstreeOrigin RpmOstreeOrigin; + /* Right now cbindgen doesn't understand types from external crates, so we hackily * typedef them. **/ @@ -31,4 +34,5 @@ b(GHashTable) b(GPtrArray) b(GChecksum) b(OstreeRepo) +b(RpmOstreeOrigin) #undef b