use std::ffi::{CStr, CString};
use std::time::SystemTime;
use libc::{c_char, c_int};
use crate::{init_logger, NMSTATE_FAIL, NMSTATE_PASS};
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn nmstate_checkpoint_commit(
checkpoint: *const c_char,
log: *mut *mut c_char,
err_kind: *mut *mut c_char,
err_msg: *mut *mut c_char,
) -> c_int {
assert!(!log.is_null());
assert!(!err_kind.is_null());
assert!(!err_msg.is_null());
unsafe {
*log = std::ptr::null_mut();
*err_kind = std::ptr::null_mut();
*err_msg = std::ptr::null_mut();
}
let logger = match init_logger() {
Ok(l) => l,
Err(e) => {
unsafe {
*err_msg = CString::new(format!("Failed to setup logger: {e}"))
.unwrap()
.into_raw();
}
return NMSTATE_FAIL;
}
};
let now = SystemTime::now();
let mut checkpoint_str = "";
if !checkpoint.is_null() {
let checkpoint_cstr = unsafe { CStr::from_ptr(checkpoint) };
checkpoint_str = match checkpoint_cstr.to_str() {
Ok(s) => s,
Err(e) => {
unsafe {
*err_msg = CString::new(format!(
"Error on converting C char to rust str: {e}"
))
.unwrap()
.into_raw();
*err_kind = CString::new(format!(
"{}",
nmstate::ErrorKind::InvalidArgument
))
.unwrap()
.into_raw();
}
return NMSTATE_FAIL;
}
}
}
let result = nmstate::NetworkState::checkpoint_commit(checkpoint_str);
unsafe {
*log = CString::new(logger.drain(now)).unwrap().into_raw();
}
if let Err(e) = result {
unsafe {
*err_msg = CString::new(e.msg()).unwrap().into_raw();
*err_kind =
CString::new(format!("{}", &e.kind())).unwrap().into_raw();
}
NMSTATE_FAIL
} else {
NMSTATE_PASS
}
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn nmstate_checkpoint_rollback(
checkpoint: *const c_char,
log: *mut *mut c_char,
err_kind: *mut *mut c_char,
err_msg: *mut *mut c_char,
) -> c_int {
assert!(!log.is_null());
assert!(!err_kind.is_null());
assert!(!err_msg.is_null());
unsafe {
*log = std::ptr::null_mut();
*err_kind = std::ptr::null_mut();
*err_msg = std::ptr::null_mut();
}
let logger = match init_logger() {
Ok(l) => l,
Err(e) => {
unsafe {
*err_msg = CString::new(format!("Failed to setup logger: {e}"))
.unwrap()
.into_raw();
}
return NMSTATE_FAIL;
}
};
let now = SystemTime::now();
let mut checkpoint_str = "";
if !checkpoint.is_null() {
let checkpoint_cstr = unsafe { CStr::from_ptr(checkpoint) };
checkpoint_str = match checkpoint_cstr.to_str() {
Ok(s) => s,
Err(e) => {
unsafe {
*err_msg = CString::new(format!(
"Error on converting C char to rust str: {e}"
))
.unwrap()
.into_raw();
*err_kind = CString::new(format!(
"{}",
nmstate::ErrorKind::InvalidArgument
))
.unwrap()
.into_raw();
}
return NMSTATE_FAIL;
}
}
}
let result = nmstate::NetworkState::checkpoint_rollback(checkpoint_str);
unsafe {
*log = CString::new(logger.drain(now)).unwrap().into_raw();
}
if let Err(e) = result {
unsafe {
*err_msg = CString::new(e.msg()).unwrap().into_raw();
*err_kind =
CString::new(format!("{}", &e.kind())).unwrap().into_raw();
}
NMSTATE_FAIL
} else {
NMSTATE_PASS
}
}