94 lines
3.2 KiB
Rust
94 lines
3.2 KiB
Rust
use ffi::OstreeSysrootDeployTreeOpts;
|
|
use glib::translate::*;
|
|
use libc::c_char;
|
|
|
|
/// Options for deploying an ostree commit.
|
|
#[derive(Default)]
|
|
pub struct SysrootDeployTreeOpts<'a> {
|
|
/// Use these kernel arguments.
|
|
pub override_kernel_argv: Option<&'a [&'a str]>,
|
|
/// Paths to initramfs files to overlay.
|
|
pub overlay_initrds: Option<&'a [&'a str]>,
|
|
}
|
|
|
|
type OptionStrSliceStorage<'a> =
|
|
<Option<&'a [&'a str]> as ToGlibPtr<'a, *mut *mut c_char>>::Storage;
|
|
|
|
impl<'a, 'b: 'a> ToGlibPtr<'a, *const OstreeSysrootDeployTreeOpts> for SysrootDeployTreeOpts<'b> {
|
|
type Storage = (
|
|
Box<OstreeSysrootDeployTreeOpts>,
|
|
OptionStrSliceStorage<'a>,
|
|
OptionStrSliceStorage<'a>,
|
|
);
|
|
|
|
fn to_glib_none(&'a self) -> Stash<*const OstreeSysrootDeployTreeOpts, Self> {
|
|
// Creating this struct from zeroed memory is fine since it's `repr(C)` and only contains
|
|
// primitive types. Zeroing it ensures we handle the unused bytes correctly.
|
|
// The struct needs to be boxed so the pointer we return remains valid even as the Stash is
|
|
// moved around.
|
|
let mut options = Box::new(unsafe { std::mem::zeroed::<OstreeSysrootDeployTreeOpts>() });
|
|
let override_kernel_argv = self.override_kernel_argv.to_glib_none();
|
|
let overlay_initrds = self.overlay_initrds.to_glib_none();
|
|
options.override_kernel_argv = override_kernel_argv.0;
|
|
options.overlay_initrds = overlay_initrds.0;
|
|
Stash(
|
|
options.as_ref(),
|
|
(options, override_kernel_argv.1, overlay_initrds.1),
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::{ffi::CStr, ptr::null_mut};
|
|
|
|
unsafe fn ptr_array_to_slice<'a, T>(ptr: *mut *mut T) -> &'a [*mut T] {
|
|
let mut len = 0;
|
|
while !(*ptr.offset(len)).is_null() {
|
|
len += 1;
|
|
}
|
|
std::slice::from_raw_parts(ptr, len as usize)
|
|
}
|
|
|
|
unsafe fn str_ptr_array_to_vec<'a>(ptr: *mut *mut c_char) -> Vec<&'a str> {
|
|
ptr_array_to_slice(ptr)
|
|
.iter()
|
|
.map(|x| CStr::from_ptr(*x).to_str().unwrap())
|
|
.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn should_convert_default_options() {
|
|
let options = SysrootDeployTreeOpts::default();
|
|
let stash = options.to_glib_none();
|
|
let ptr = stash.0;
|
|
unsafe {
|
|
assert_eq!((*ptr).override_kernel_argv, null_mut());
|
|
assert_eq!((*ptr).overlay_initrds, null_mut());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn should_convert_non_default_options() {
|
|
let override_kernel_argv = vec!["quiet", "splash", "ro"];
|
|
let overlay_initrds = vec!["overlay1", "overlay2"];
|
|
let options = SysrootDeployTreeOpts {
|
|
override_kernel_argv: Some(&override_kernel_argv),
|
|
overlay_initrds: Some(&overlay_initrds),
|
|
};
|
|
let stash = options.to_glib_none();
|
|
let ptr = stash.0;
|
|
unsafe {
|
|
assert_eq!(
|
|
str_ptr_array_to_vec((*ptr).override_kernel_argv),
|
|
vec!["quiet", "splash", "ro"]
|
|
);
|
|
assert_eq!(
|
|
str_ptr_array_to_vec((*ptr).overlay_initrds),
|
|
vec!["overlay1", "overlay2"]
|
|
);
|
|
}
|
|
}
|
|
}
|