-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use cxx-rs for core.rs #2336
Use cxx-rs for core.rs #2336
Changes from 3 commits
10cdecf
1b7efe7
cc6e2e2
b52c83f
56012db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/usr/bin/bash | ||
# Install build dependencies not in the cosa buildroot already | ||
set -xeuo pipefail | ||
if ! command -v cxxbridge; then | ||
ver=$(cargo metadata --format-version 1 | jq -r '.packages[]|select(.name == "cxx").version') | ||
cargo install --root=/usr cxxbridge-cmd --version "${ver}" | ||
fi |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
pub use self::ffi::*; | ||
use crate::ffiutil; | ||
use anyhow::Result; | ||
use ffiutil::ffi_view_openat_dir; | ||
use openat_ext::OpenatDirExt; | ||
|
||
/// Guard for running logic in a context with temporary /etc. | ||
|
@@ -13,27 +14,27 @@ pub struct TempEtcGuard { | |
renamed_etc: bool, | ||
} | ||
|
||
impl TempEtcGuard { | ||
/// Create a context with a temporary /etc, and return a guard to it. | ||
pub fn undo_usretc(rootfs: openat::Dir) -> anyhow::Result<Self> { | ||
let has_usretc = rootfs.exists("usr/etc")?; | ||
if has_usretc { | ||
// In general now, we place contents in /etc when running scripts | ||
rootfs.local_rename("usr/etc", "etc")?; | ||
// But leave a compat symlink, as we used to bind mount, so scripts | ||
// could still use that too. | ||
rootfs.symlink("usr/etc", "../etc")?; | ||
} | ||
|
||
let guard = Self { | ||
rootfs, | ||
renamed_etc: has_usretc, | ||
}; | ||
Ok(guard) | ||
pub fn prepare_tempetc_guard(rootfs: i32) -> Result<Box<TempEtcGuard>> { | ||
let rootfs = ffi_view_openat_dir(rootfs); | ||
let has_usretc = rootfs.exists("usr/etc")?; | ||
let mut renamed_etc = false; | ||
if has_usretc { | ||
// In general now, we place contents in /etc when running scripts | ||
rootfs.local_rename("usr/etc", "etc")?; | ||
// But leave a compat symlink, as we used to bind mount, so scripts | ||
// could still use that too. | ||
rootfs.symlink("usr/etc", "../etc")?; | ||
renamed_etc = true; | ||
} | ||
Ok(Box::new(TempEtcGuard { | ||
rootfs, | ||
renamed_etc, | ||
})) | ||
} | ||
|
||
impl TempEtcGuard { | ||
/// Remove the temporary /etc, and destroy the guard. | ||
pub fn redo_usretc(self) -> anyhow::Result<()> { | ||
pub fn undo(&self) -> anyhow::Result<()> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be cool if we could we make the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do that actually! But I explicitly chose not to because there's no way to check for errors in |
||
if self.renamed_etc { | ||
/* Remove the symlink and swap back */ | ||
self.rootfs.remove_file("usr/etc")?; | ||
|
@@ -43,28 +44,24 @@ impl TempEtcGuard { | |
} | ||
} | ||
|
||
mod ffi { | ||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use glib_sys::GError; | ||
|
||
#[no_mangle] | ||
pub extern "C" fn ror_tempetc_undo_usretc( | ||
rootfs: libc::c_int, | ||
gerror: *mut *mut GError, | ||
) -> *mut TempEtcGuard { | ||
let fd = ffiutil::ffi_view_openat_dir(rootfs); | ||
let res = TempEtcGuard::undo_usretc(fd).map(Box::new); | ||
ffiutil::ptr_glib_error(res, gerror) | ||
} | ||
use std::os::unix::prelude::*; | ||
|
||
#[no_mangle] | ||
pub extern "C" fn ror_tempetc_redo_usretc( | ||
guard_ptr: *mut TempEtcGuard, | ||
gerror: *mut *mut GError, | ||
) -> libc::c_int { | ||
assert!(!guard_ptr.is_null()); | ||
let guard = unsafe { Box::from_raw(guard_ptr) }; | ||
let res = guard.redo_usretc(); | ||
ffiutil::int_glib_error(res, gerror) | ||
#[test] | ||
fn basic() -> Result<()> { | ||
let td = tempfile::tempdir()?; | ||
let d = openat::Dir::open(td.path())?; | ||
let g = super::prepare_tempetc_guard(d.as_raw_fd())?; | ||
g.undo()?; | ||
d.ensure_dir_all("usr/etc/foo", 0o755)?; | ||
assert!(!d.exists("etc/foo")?); | ||
let g = super::prepare_tempetc_guard(d.as_raw_fd())?; | ||
assert!(d.exists("etc/foo")?); | ||
g.undo()?; | ||
assert!(!d.exists("etc")?); | ||
assert!(d.exists("usr/etc/foo")?); | ||
Ok(()) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,11 +10,23 @@ | |
mod ffiutil; | ||
mod includes; | ||
|
||
#[cxx::bridge(namespace = "rpmostreecxx")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the namespace name be e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah but see it's bidirectional, cxx supports Rust calling C++ too and I just submitted #2413 to demo that. That said it could totally use a better name.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OTOH we can also change the name later; there's not a lot of code using this right now. It'll just get slightly more expensive to do so as usage increases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked at this a bit more. It's an interesting topic; partly comes down to whether we see the "cxxrs" part as separate from the C/C++ part. And the core question there is, do we stick everything in the C++ side into the same This also conceptually would lead towards dropping the C function prefixing, e.g. instead of So I think for now let's just keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right OK, got it. WDYT about Also, definitely agreed re. not trying to make too much use of namespaces outside of cxxrs. |
||
mod ffi { | ||
// core.rs | ||
extern "Rust" { | ||
type TempEtcGuard; | ||
|
||
fn prepare_tempetc_guard(rootfs: i32) -> Result<Box<TempEtcGuard>>; | ||
fn undo(self: &TempEtcGuard) -> Result<()>; | ||
} | ||
} | ||
|
||
mod cliwrap; | ||
pub use cliwrap::*; | ||
mod composepost; | ||
pub use self::composepost::*; | ||
mod core; | ||
use crate::core::*; | ||
mod history; | ||
pub use self::history::*; | ||
mod journal; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From an out-of-band chat: this seems to be a
cxx
limitation, not being able to consume the ownership of the object itself.