use blenv::Environment;
use bls::BLSEntry;
use cmdline::{CmdlineHandler, CmdlineParam};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char};
use std::slice;
#[repr(C)]
pub struct CTraitReference {
data: *mut std::os::raw::c_void,
vtable: *mut std::os::raw::c_void
}
extern "C" {
fn malloc(size: usize) -> *mut u8;
}
fn utf8_to_malloc (string: &str) -> *mut c_char {
unsafe {
let bytes = string.as_bytes();
let len_with_zero = bytes.len() + 1;
let buffer = malloc(len_with_zero);
if buffer != std::ptr::null_mut() {
let dest = slice::from_raw_parts_mut(buffer, len_with_zero);
dest.copy_from_slice(bytes);
dest[bytes.len()] = 0;
}
buffer as *mut _
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_new (clamped: usize, filepath: *const i8) -> *mut Environment {
let clamp = match clamped {
0 => { None },
_ => { Some(clamped.clone()) }
};
let filepath = match unsafe { CStr::from_ptr(filepath).to_str() } {
Ok(filepath) => filepath,
Err(err) => { panic!("Invalid path string to bootloader environment file: {}", err); }
};
match Environment::new(clamp, filepath) {
Ok(env) => Box::into_raw(Box::new(env)),
Err(e) => {
eprintln!("Could not read or create grubenv file: {}", e);
std::ptr::null_mut()
}
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_destroy(env: *mut Environment) {
let _env = unsafe { Box::from_raw(env) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_show (env: *mut Environment) -> *mut c_char {
let env = unsafe { Box::from_raw(env) };
let env_render = match env.show() {
Ok(env_render) => env_render,
_ => { return std::ptr::null_mut(); }
};
Box::into_raw(env);
utf8_to_malloc(&env_render)
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_get (env: *mut Environment, key: *const i8) -> *mut c_char {
let env = unsafe { Box::from_raw(env) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() { Ok(key) => key, _ => { return std::ptr::null_mut() }};
let ret = match env.get(key) {
Ok(value) => utf8_to_malloc(&value),
_ => std::ptr::null_mut()
};
Box::into_raw(env);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_set (env: *mut Environment, key: *const i8, value: *const i8) -> c_char {
let env = unsafe { Box::from_raw(env) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() { Ok(key) => key, _ => { return 0 }};
let value = match unsafe { CStr::from_ptr(value) }.to_str() { Ok(value) => value, _ => { return 0 }};
let ret = env.set(key, value);
Box::into_raw(env);
match ret {
Ok(_) => 1,
Err(_) => 0
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_unset (env: *mut Environment, key: *const i8) -> c_char {
let env = unsafe { Box::from_raw(env) };
let key = match unsafe { CStr::from_ptr(key) }.to_str() { Ok(key) => key, _ => { return 0 }};
let ret = env.unset(key);
Box::into_raw(env);
match ret {
Ok(_) => 1,
Err(_) => 0
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_cmdline_render(env: *mut Environment) -> *mut c_char {
let env = unsafe { Box::from_raw(env)};
let render = env.cmdline_render();
Box::into_raw(env);
if let Ok(render) = render {
return utf8_to_malloc(&render);
} else {
std::ptr::null_mut()
}
}
fn generic_cmdline_handler(env: &mut CmdlineHandler, params: *const *const c_char, op: &Fn(&mut CmdlineHandler, &[String]) -> std::io::Result<()>) -> c_char {
let start: *mut usize = params as *mut usize;
let mut end: isize = 0;
let mut boxed_address = unsafe { std::ptr::read (start.offset(end))};
while boxed_address != 0 {
boxed_address = unsafe { std::ptr::read (start.offset(end))};
end += 1;
}
end -= 1;
let ptr_slice = unsafe { std::slice::from_raw_parts(params, end as usize) };
let params: Vec<_> = ptr_slice.iter()
.map(|cstr| { unsafe { CStr::from_ptr(*cstr) }})
.map(|cstr| { cstr.to_str() })
.filter_map(|cstr| { match cstr {
Err(_) => None,
Ok(params) => Some(params)
}})
.map(|param| { String::from(param) })
.collect();
if params.len() != end as usize {
return 0;
}
match op(env, ¶ms[..]) {
Ok(_) => 1,
Err(_) => 0
}
}
fn generic_cmdline_get (env: &mut CmdlineHandler, param: *const c_char) -> *mut CmdlineParam {
let param = match unsafe { CStr::from_ptr(param) }.to_str() {
Ok(param) => param,
Err(_) => { return std::ptr::null_mut(); }
};
let cmdline = env.cmdline_get(&String::from(param));
match cmdline {
Ok(cmdline) => {
let cmdline = Box::new(cmdline);
Box::into_raw(cmdline)
}
Err(_) => std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub 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) {
let cmdline = unsafe{ Box::from_raw(cmdline) };
for param_value in cmdline.iter() {
match param_value {
Some(param_value) => {
let c_param_value = CString::new(param_value.as_str()).unwrap();
lambda (c_param_value.as_ptr(), user_data);
}
None => {
lambda (std::ptr::null(), user_data);
}
}
};
Box::into_raw(cmdline);
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_param_get_size (cmdline: *mut CmdlineParam) -> usize {
let cmdline = unsafe{ Box::from_raw(cmdline) };
let size = cmdline.len();
Box::into_raw(cmdline);
size
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_param_destroy(cmdline: *mut CmdlineParam) {
unsafe{ Box::from_raw(cmdline) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_new(entry: *const c_char) -> *mut BLSEntry {
let entry = match unsafe { CStr::from_ptr(entry) }.to_str() {
Ok(entry_name) => String::from(entry_name),
Err(_) => { return std::ptr::null_mut(); }
};
if let Ok(entry) = BLSEntry::new(&entry) {
Box::into_raw(Box::new(entry))
} else {
std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_destroy(entry: *mut BLSEntry) {
unsafe { Box::from_raw(entry) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_get (entry: *mut BLSEntry, command: *const c_char) -> *mut c_char {
let entry = unsafe { Box::from_raw(entry) };
let command = match unsafe { CStr::from_ptr(command) }.to_str() {
Ok(command) => command,
_ => { return std::ptr::null_mut(); }
};
let ret = match entry.get(command) {
Ok(arg) => {
utf8_to_malloc(&arg)
},
_ => std::ptr::null_mut()
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_set (entry: *mut BLSEntry, command: *const c_char, arg: *const c_char) -> c_char {
let entry = unsafe { Box::from_raw(entry) };
let command = match unsafe { CStr::from_ptr(command) }.to_str() {
Ok(command) => command,
_ => { return 0; }
};
let arg = match unsafe { CStr::from_ptr(arg) }.to_str() {
Ok(arg) => arg,
_ => { return 0; }
};
let ret = match entry.set(command, String::from(arg)) {
Ok(_) => 1,
_ => 0
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_remove (entry: *mut BLSEntry, command: *const c_char) -> c_char {
let entry = unsafe { Box::from_raw(entry) };
let command = match unsafe { CStr::from_ptr(command) }.to_str() {
Ok(command) => command,
_ => { return 0; }
};
let ret = match entry.remove(command) {
Ok(_) => 1,
_ => 0
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list () -> *mut Vec<String> {
match BLSEntry::get_bls_entries() {
Ok(entries) => {
Box::into_raw(Box::new(entries))
},
Err(_) => std::ptr::null_mut()
}
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list_destroy(list: *mut Vec<String>) {
let _ = unsafe { Box::from_raw(list) };
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_env_to_cmdline (env: *mut Environment) -> CTraitReference {
let mut env = unsafe { Box::from_raw(env) };
let ret: CTraitReference = {
let handler: &mut dyn CmdlineHandler = &mut *env;
unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
};
Box::into_raw(env);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_to_cmdline (entry: *mut BLSEntry) -> CTraitReference {
let mut entry = unsafe { Box::from_raw(entry) };
let ret: CTraitReference = {
let handler: &mut dyn CmdlineHandler = &mut *entry;
unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
};
Box::into_raw(entry);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_entry_list_to_cmdline (list: *mut Vec<String>) -> CTraitReference {
let mut list = unsafe { Box::from_raw(list) };
let ret: CTraitReference = {
let handler: &mut dyn CmdlineHandler = &mut *list;
unsafe { std::mem::transmute::<&mut dyn CmdlineHandler,CTraitReference> (handler) }
};
Box::into_raw(list);
ret
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_get (handler: CTraitReference, param: *mut c_char) -> *mut CmdlineParam {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_get (handler, param)
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_set (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_set(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_add (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_add(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_remove (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_remove(p) })
}
#[allow(dead_code)]
#[no_mangle]
pub extern "C" fn bls_cmdline_clear (handler: CTraitReference, params: *const *const c_char) -> c_char {
let handler = unsafe { std::mem::transmute::<CTraitReference, &mut dyn CmdlineHandler> (handler) };
generic_cmdline_handler(handler, params, &|e, p| { e.cmdline_clear(p) })
}