1use std::ffi::{CStr, CString};
4use std::time::SystemTime;
5
6use libc::{c_char, c_int};
7
8use crate::{init_logger, NMSTATE_FAIL, NMSTATE_PASS};
9
10#[allow(clippy::not_unsafe_ptr_arg_deref)]
11#[no_mangle]
12pub extern "C" fn nmstate_checkpoint_commit(
13 checkpoint: *const c_char,
14 log: *mut *mut c_char,
15 err_kind: *mut *mut c_char,
16 err_msg: *mut *mut c_char,
17) -> c_int {
18 assert!(!log.is_null());
19 assert!(!err_kind.is_null());
20 assert!(!err_msg.is_null());
21
22 unsafe {
23 *log = std::ptr::null_mut();
24 *err_kind = std::ptr::null_mut();
25 *err_msg = std::ptr::null_mut();
26 }
27
28 let logger = match init_logger() {
29 Ok(l) => l,
30 Err(e) => {
31 unsafe {
32 *err_msg = CString::new(format!("Failed to setup logger: {e}"))
33 .unwrap()
34 .into_raw();
35 }
36 return NMSTATE_FAIL;
37 }
38 };
39 let now = SystemTime::now();
40
41 let mut checkpoint_str = "";
42 if !checkpoint.is_null() {
43 let checkpoint_cstr = unsafe { CStr::from_ptr(checkpoint) };
44 checkpoint_str = match checkpoint_cstr.to_str() {
45 Ok(s) => s,
46 Err(e) => {
47 unsafe {
48 *err_msg = CString::new(format!(
49 "Error on converting C char to rust str: {e}"
50 ))
51 .unwrap()
52 .into_raw();
53 *err_kind = CString::new(format!(
54 "{}",
55 nmstate::ErrorKind::InvalidArgument
56 ))
57 .unwrap()
58 .into_raw();
59 }
60 return NMSTATE_FAIL;
61 }
62 }
63 }
64
65 let result = nmstate::NetworkState::checkpoint_commit(checkpoint_str);
66 unsafe {
67 *log = CString::new(logger.drain(now)).unwrap().into_raw();
68 }
69
70 if let Err(e) = result {
71 unsafe {
72 *err_msg = CString::new(e.msg()).unwrap().into_raw();
73 *err_kind =
74 CString::new(format!("{}", &e.kind())).unwrap().into_raw();
75 }
76 NMSTATE_FAIL
77 } else {
78 NMSTATE_PASS
79 }
80}
81
82#[allow(clippy::not_unsafe_ptr_arg_deref)]
83#[no_mangle]
84pub extern "C" fn nmstate_checkpoint_rollback(
85 checkpoint: *const c_char,
86 log: *mut *mut c_char,
87 err_kind: *mut *mut c_char,
88 err_msg: *mut *mut c_char,
89) -> c_int {
90 assert!(!log.is_null());
91 assert!(!err_kind.is_null());
92 assert!(!err_msg.is_null());
93
94 unsafe {
95 *log = std::ptr::null_mut();
96 *err_kind = std::ptr::null_mut();
97 *err_msg = std::ptr::null_mut();
98 }
99
100 let logger = match init_logger() {
101 Ok(l) => l,
102 Err(e) => {
103 unsafe {
104 *err_msg = CString::new(format!("Failed to setup logger: {e}"))
105 .unwrap()
106 .into_raw();
107 }
108 return NMSTATE_FAIL;
109 }
110 };
111 let now = SystemTime::now();
112
113 let mut checkpoint_str = "";
114 if !checkpoint.is_null() {
115 let checkpoint_cstr = unsafe { CStr::from_ptr(checkpoint) };
116 checkpoint_str = match checkpoint_cstr.to_str() {
117 Ok(s) => s,
118 Err(e) => {
119 unsafe {
120 *err_msg = CString::new(format!(
121 "Error on converting C char to rust str: {e}"
122 ))
123 .unwrap()
124 .into_raw();
125 *err_kind = CString::new(format!(
126 "{}",
127 nmstate::ErrorKind::InvalidArgument
128 ))
129 .unwrap()
130 .into_raw();
131 }
132 return NMSTATE_FAIL;
133 }
134 }
135 }
136
137 let result = nmstate::NetworkState::checkpoint_rollback(checkpoint_str);
139 unsafe {
140 *log = CString::new(logger.drain(now)).unwrap().into_raw();
141 }
142
143 if let Err(e) = result {
144 unsafe {
145 *err_msg = CString::new(e.msg()).unwrap().into_raw();
146 *err_kind =
147 CString::new(format!("{}", &e.kind())).unwrap().into_raw();
148 }
149 NMSTATE_FAIL
150 } else {
151 NMSTATE_PASS
152 }
153}