Skip to main content

blsctl/
cshim.rs

1// cshim.rs
2//
3// Copyright 2019 Alberto Ruiz <aruiz@gnome.org>
4//
5// This file is free software; you can redistribute it and/or modify it
6// under the terms of the GNU Lesser General Public License as
7// published by the Free Software Foundation; either version 2.1 of the
8// License, or (at your option) any later version.
9//
10// This file is distributed in the hope that it will be useful, but
11// WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this program.  If not, see <http://www.gnu.org/licenses/>.
17//
18// SPDX-License-Identifier: LGPL-2.1-or-later
19
20use crate::bls::{BLSEntry, KeyValue};
21use crate::cmdline::{CmdlineHandler, CmdlineParam};
22use std::ffi::{CStr, CString};
23use std::os::raw::{c_char};
24
25#[repr(C)]
26pub struct CTraitReference {
27  data: *mut std::os::raw::c_void,
28  vtable: *mut std::os::raw::c_void
29}
30
31fn c_array_to_vector(c_array: *const *const c_char) -> Result<Vec<String>, &'static str> {
32  /* Find null pointer to assess end of array */
33  let start: *mut usize = c_array as *mut usize;
34  let mut end: isize = 0;
35  let mut boxed_address = unsafe { std::ptr::read (start.offset(end))};
36  while boxed_address != 0 {
37    boxed_address = unsafe { std::ptr::read (start.offset(end))};
38    end += 1;
39  }
40  end -= 1;
41
42  let ptr_slice = unsafe { std::slice::from_raw_parts(c_array, end as usize) };
43  let vector: Vec<_> = ptr_slice.iter()
44    .map(|cstr| { unsafe { CStr::from_ptr(*cstr) }})
45    .map(|cstr| { cstr.to_str() })
46    .filter_map(|cstr| { match cstr {
47      Err(_) => None,
48      Ok(elements) => Some(elements)
49    }})
50    .map(|element| { String::from(element) })
51    .collect();
52
53  if vector.len() != end as usize {
54    return Err("could not convert pointer to vector");
55  }
56
57  Ok(vector)
58}
59
60fn generic_cmdline_handler(env: &mut dyn CmdlineHandler, params: *const *const c_char, op: &dyn Fn(&mut dyn CmdlineHandler, &[String]) -> std::io::Result<()>) -> c_char {
61  let params = match c_array_to_vector(params) {
62    Ok(params) => params,
63    Err(_) => { return 0; }
64  };
65
66  match op(env, &params[..]) {
67    Ok(_) =>   1,
68    Err(_) =>  0
69  }
70}
71
72fn generic_cmdline_get (env: &mut dyn CmdlineHandler, param: *const c_char) -> *mut CmdlineParam {
73  let param = match unsafe { CStr::from_ptr(param) }.to_str() {
74    Ok(param) => param,
75    Err(_) => { return std::ptr::null_mut(); }
76  };
77
78  let cmdline = env.cmdline_get(&String::from(param));
79
80  match cmdline {
81    Ok(cmdline) => {
82      let cmdline = Box::new(cmdline);
83      Box::into_raw(cmdline)
84    }
85    Err(_) => std::ptr::null_mut()
86  }
87}
88
89#[allow(dead_code)]
90#[no_mangle]
91pub extern "C" fn bls_cmdline_param_foreach (cmdline: *mut CmdlineParam, lambda: extern "C" fn (val: *const c_char, user_data: *mut std::ffi::c_void), user_data: *mut std::ffi::c_void) {
92    let cmdline = unsafe{ Box::from_raw(cmdline) };
93    for param_value in cmdline.iter() {
94      match param_value {
95        Some(param_value) => {
96          let c_param_value = CString::new(param_value.as_str()).unwrap();
97
98          lambda (c_param_value.as_ptr(), user_data);
99        }
100        None => {
101          lambda (std::ptr::null(), user_data);
102        }
103      }
104    };
105    Box::into_raw(cmdline);
106}
107
108
109#[allow(dead_code)]
110#[no_mangle]
111pub extern "C" fn bls_cmdline_param_get_size (cmdline: *mut CmdlineParam) -> usize {
112  let cmdline = unsafe{ Box::from_raw(cmdline) };
113  let size = cmdline.len();
114  Box::into_raw(cmdline);
115  size
116}
117
118#[allow(dead_code)]
119#[no_mangle]
120pub extern "C" fn bls_cmdline_param_destroy(cmdline: *mut CmdlineParam) {
121  unsafe{ Box::from_raw(cmdline) };
122}
123
124/* BLS Entry */
125
126#[allow(dead_code)]
127#[no_mangle]
128pub extern "C" fn bls_entry_new(entry: *const c_char) -> *mut BLSEntry {
129  let entry = match unsafe { CStr::from_ptr(entry) }.to_str() {
130    Ok(entry_name) => String::from(entry_name),
131    Err(_) => { return std::ptr::null_mut(); }
132  };
133
134  if let Ok(entry) = BLSEntry::new(&entry) {
135    Box::into_raw(Box::new(entry))
136  } else {
137    std::ptr::null_mut()
138  }
139}
140
141#[allow(dead_code)]
142#[no_mangle]
143pub extern "C" fn bls_entry_destroy(entry: *mut BLSEntry) {
144  unsafe { Box::from_raw(entry) };
145}
146
147#[allow(dead_code)]
148#[no_mangle]
149pub extern "C" fn bls_entry_get (entry: *mut BLSEntry, key: *const c_char) -> *mut KeyValue {
150  let entry = unsafe { Box::from_raw(entry) };
151  let key = match unsafe { CStr::from_ptr(key) }.to_str() {
152    Ok(key) => key,
153    _ => { return std::ptr::null_mut(); }
154  };
155
156 match entry.get(key) {
157   Ok(keyvalue) => {
158     let keyvalue = Box::new(keyvalue);
159     Box::into_raw(keyvalue)
160    },
161    Err(_) => std::ptr::null_mut()
162  }
163}
164
165#[allow(dead_code)]
166#[no_mangle]
167pub extern "C" fn bls_entry_set (entry: *mut BLSEntry, key: *const c_char,
168                                 value: *const *const c_char) -> c_char {
169  let entry = unsafe { Box::from_raw(entry) };
170  let key = match unsafe { CStr::from_ptr(key) }.to_str() {
171    Ok(key) => key,
172    _ => { return 0; }
173  };
174
175 let value = match c_array_to_vector(value) {
176    Ok(value) => value,
177    Err(_) => { return 0; }
178  };
179
180  let ret = match entry.set(key, &value) {
181    Ok(_) => 1,
182    _ => 0
183  };
184  Box::into_raw(entry);
185  ret
186}
187
188#[allow(dead_code)]
189#[no_mangle]
190pub extern "C" fn bls_entry_remove (entry: *mut BLSEntry, key: *const c_char) -> c_char {
191  let entry = unsafe { Box::from_raw(entry) };
192  let key = match unsafe { CStr::from_ptr(key) }.to_str() {
193    Ok(key) => key,
194    _ => { return 0; }
195  };
196
197  let ret = match entry.remove(key) {
198    Ok(_) => 1,
199    _ => 0
200  };
201  Box::into_raw(entry);
202  ret
203}
204
205/* BLSEntryList */
206
207#[allow(dead_code)]
208#[no_mangle]
209pub extern "C" fn bls_entry_list () -> *mut Vec<String> {
210  match BLSEntry::get_bls_entries() {
211    Ok(entries) => {
212      Box::into_raw(Box::new(entries))
213    },
214    Err(_) => std::ptr::null_mut()
215  }
216}
217
218#[allow(dead_code)]
219#[no_mangle]
220pub extern "C" fn bls_entry_list_destroy(list: *mut Vec<String>) {
221  let _ = unsafe { Box::from_raw(list) };
222}
223
224/* Cmdline related methods */
225
226#[allow(dead_code)]
227#[no_mangle]
228pub extern "C" fn bls_entry_to_cmdline (entry: *mut BLSEntry) -> CTraitReference {
229  let mut entry = unsafe { Box::from_raw(entry) };
230  let ret: CTraitReference = {
231    let handler: &mut dyn CmdlineHandler = &mut *entry;
232    unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
233  };
234  Box::into_raw(entry);
235  ret
236}
237
238#[allow(dead_code)]
239#[no_mangle]
240pub extern "C" fn bls_entry_list_to_cmdline (list: *mut Vec<String>) -> CTraitReference {
241  let mut list = unsafe { Box::from_raw(list) };
242  let ret: CTraitReference = {
243    let handler: &mut dyn CmdlineHandler = &mut *list;
244    unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
245  };
246  Box::into_raw(list);
247  ret
248}
249
250#[allow(dead_code)]
251#[no_mangle]
252pub extern "C" fn bls_cmdline_get (handler: CTraitReference, param: *mut c_char) -> *mut CmdlineParam {
253  let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
254  generic_cmdline_get (handler, param)
255}
256
257#[allow(dead_code)]
258#[no_mangle]
259pub extern "C" fn bls_cmdline_set (handler: CTraitReference, params: *const *const c_char) -> c_char {
260  let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
261  generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_set(p) })
262
263}
264
265#[allow(dead_code)]
266#[no_mangle]
267pub extern "C" fn bls_cmdline_add (handler: CTraitReference, params: *const *const c_char) -> c_char {
268  let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
269  generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_add(p) })
270}
271
272#[allow(dead_code)]
273#[no_mangle]
274pub extern "C" fn bls_cmdline_remove (handler: CTraitReference, params: *const *const c_char) -> c_char {
275  let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
276  generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_remove(p) })
277}
278
279#[allow(dead_code)]
280#[no_mangle]
281pub extern "C" fn bls_cmdline_clear (handler: CTraitReference, params: *const *const c_char) -> c_char {
282  let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
283  generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_clear(p) })
284}