use std::ffi::{self, c_char};
use crate::{device, ffi_guard, into_c_string, util};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ts_taildrop_waiting_files(
dev: &device,
out: *mut *mut c_char,
) -> ffi::c_int {
ffi_guard(move || {
let files = match dev.0.taildrop_waiting_files() {
Ok(files) => files,
Err(e) => {
tracing::error!(err = %e, "taildrop_waiting_files");
unsafe { *out = std::ptr::null_mut() };
return -1;
}
};
if files.is_empty() {
unsafe { *out = std::ptr::null_mut() };
return 0;
}
let count = files.len() as ffi::c_int;
let joined = files
.into_iter()
.map(|f| f.name)
.collect::<Vec<_>>()
.join("\n");
let ptr = into_c_string(joined);
if ptr.is_null() {
return -1;
}
unsafe { *out = ptr };
count
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ts_taildrop_file_size(
dev: &device,
name: *const c_char,
out_size: &mut u64,
) -> ffi::c_int {
ffi_guard(move || {
let Some(name) = (unsafe { util::str(name) }) else {
tracing::error!("taildrop_file_size: name is null or invalid utf-8");
return -1;
};
match dev.0.taildrop_open_file(name) {
Ok((_file, size)) => {
*out_size = size;
0
}
Err(e) => {
tracing::error!(err = %e, "taildrop_file_size");
-1
}
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ts_taildrop_save_file(
dev: &device,
name: *const c_char,
dst_path: *const c_char,
) -> ffi::c_int {
ffi_guard(move || {
let (Some(name), Some(dst_path)) = (unsafe { (util::str(name), util::str(dst_path)) })
else {
tracing::error!("taildrop_save_file: a string argument is null or invalid utf-8");
return -1;
};
let (mut src, _size) = match dev.0.taildrop_open_file(name) {
Ok(opened) => opened,
Err(e) => {
tracing::error!(err = %e, "taildrop_save_file: open source");
return -1;
}
};
let mut dst = match std::fs::File::create(dst_path) {
Ok(f) => f,
Err(e) => {
tracing::error!(err = %e, "taildrop_save_file: create destination");
return -1;
}
};
match std::io::copy(&mut src, &mut dst) {
Ok(_) => 0,
Err(e) => {
tracing::error!(err = %e, "taildrop_save_file: copy");
-1
}
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ts_taildrop_delete_file(dev: &device, name: *const c_char) -> ffi::c_int {
ffi_guard(move || {
let Some(name) = (unsafe { util::str(name) }) else {
tracing::error!("taildrop_delete_file: name is null or invalid utf-8");
return -1;
};
match dev.0.taildrop_delete_file(name) {
Ok(()) => 0,
Err(e) => {
tracing::error!(err = %e, "taildrop_delete_file");
-1
}
}
})
}