26.0.1
This commit is contained in:
@@ -17,6 +17,13 @@ pub struct BackendHolder {
|
||||
pub drive: Box<dyn Drive>,
|
||||
}
|
||||
|
||||
fn ffi_guard<T>(default: T, f: impl FnOnce() -> T) -> T {
|
||||
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
|
||||
Ok(value) => value,
|
||||
Err(_) => default,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn cstr(s: &str) -> *mut c_char {
|
||||
let clean: String = s.chars().filter(|c| *c != '\0').collect();
|
||||
match CString::new(clean) {
|
||||
@@ -212,6 +219,16 @@ pub unsafe extern "C" fn cdda_identify(
|
||||
device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
ffi_guard(ptr::null_mut(), || {
|
||||
cdda_identify_impl(device, messagedest, messages)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn cdda_identify_impl(
|
||||
device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
if !messages.is_null() {
|
||||
*messages = ptr::null_mut();
|
||||
@@ -234,6 +251,16 @@ pub unsafe extern "C" fn cdda_identify_cooked(
|
||||
device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
ffi_guard(ptr::null_mut(), || {
|
||||
cdda_identify_cooked_impl(device, messagedest, messages)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn cdda_identify_cooked_impl(
|
||||
device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
if !messages.is_null() {
|
||||
*messages = ptr::null_mut();
|
||||
@@ -257,6 +284,17 @@ pub unsafe extern "C" fn cdda_identify_scsi(
|
||||
ioctl_device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
ffi_guard(ptr::null_mut(), || {
|
||||
cdda_identify_scsi_impl(generic_device, ioctl_device, messagedest, messages)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn cdda_identify_scsi_impl(
|
||||
generic_device: *const c_char,
|
||||
ioctl_device: *const c_char,
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
if !messages.is_null() {
|
||||
*messages = ptr::null_mut();
|
||||
@@ -289,6 +327,15 @@ pub unsafe extern "C" fn cdda_identify_scsi(
|
||||
pub unsafe extern "C" fn cdda_find_a_cdrom(
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
ffi_guard(ptr::null_mut(), || {
|
||||
cdda_find_a_cdrom_impl(messagedest, messages)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn cdda_find_a_cdrom_impl(
|
||||
messagedest: c_int,
|
||||
messages: *mut *mut c_char,
|
||||
) -> *mut CdromDrive {
|
||||
if !messages.is_null() {
|
||||
*messages = ptr::null_mut();
|
||||
@@ -301,6 +348,10 @@ pub unsafe extern "C" fn cdda_find_a_cdrom(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn cdda_open(d: *mut CdromDrive) -> c_int {
|
||||
ffi_guard(-100, || cdda_open_impl(d))
|
||||
}
|
||||
|
||||
unsafe fn cdda_open_impl(d: *mut CdromDrive) -> c_int {
|
||||
if d.is_null() {
|
||||
return -100;
|
||||
}
|
||||
@@ -343,6 +394,10 @@ pub unsafe extern "C" fn cdda_open(d: *mut CdromDrive) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn cdda_close(d: *mut CdromDrive) -> c_int {
|
||||
ffi_guard(0, || cdda_close_impl(d))
|
||||
}
|
||||
|
||||
unsafe fn cdda_close_impl(d: *mut CdromDrive) -> c_int {
|
||||
if d.is_null() {
|
||||
return 0;
|
||||
}
|
||||
@@ -357,6 +412,18 @@ pub unsafe extern "C" fn cdda_read_timed(
|
||||
beginsector: c_long,
|
||||
sectors: c_long,
|
||||
ms: *mut c_int,
|
||||
) -> c_long {
|
||||
ffi_guard(-1, || {
|
||||
cdda_read_timed_impl(d, buffer, beginsector, sectors, ms)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn cdda_read_timed_impl(
|
||||
d: *mut CdromDrive,
|
||||
buffer: *mut c_void,
|
||||
beginsector: c_long,
|
||||
sectors: c_long,
|
||||
ms: *mut c_int,
|
||||
) -> c_long {
|
||||
if !ms.is_null() {
|
||||
*ms = -1;
|
||||
@@ -422,6 +489,10 @@ pub unsafe extern "C" fn cdda_read(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn cdda_speed_set(d: *mut CdromDrive, speed: c_int) -> c_int {
|
||||
ffi_guard(-405, || cdda_speed_set_impl(d, speed))
|
||||
}
|
||||
|
||||
unsafe fn cdda_speed_set_impl(d: *mut CdromDrive, speed: c_int) -> c_int {
|
||||
match holder(d) {
|
||||
Some(h) => {
|
||||
let ret = h.drive.speed_set(speed);
|
||||
@@ -569,3 +640,81 @@ pub unsafe extern "C" fn cdda_track_bitmap(
|
||||
// Keep the c_long import used on all targets.
|
||||
#[allow(dead_code)]
|
||||
fn _typecheck(_: c_long) {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use cdrustanoia_core::device::{DiscToc, InterfaceKind, ReadError, TimedRead};
|
||||
|
||||
struct PanicDrive {
|
||||
toc: DiscToc,
|
||||
}
|
||||
|
||||
impl Drive for PanicDrive {
|
||||
fn toc(&self) -> &DiscToc {
|
||||
&self.toc
|
||||
}
|
||||
fn toc_mut(&mut self) -> &mut DiscToc {
|
||||
&mut self.toc
|
||||
}
|
||||
fn opened(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn open_disc(&mut self) -> Result<(), String> {
|
||||
panic!("intentional test panic");
|
||||
}
|
||||
fn read_audio(
|
||||
&mut self,
|
||||
_buffer: Option<&mut [u8]>,
|
||||
_begin: i64,
|
||||
_sectors: i64,
|
||||
) -> Result<usize, ReadError> {
|
||||
Err(ReadError::closed())
|
||||
}
|
||||
fn read_timed(
|
||||
&mut self,
|
||||
_buffer: Option<&mut [u8]>,
|
||||
_begin: i64,
|
||||
_sectors: i64,
|
||||
) -> TimedRead {
|
||||
TimedRead {
|
||||
result: Err(ReadError::closed()),
|
||||
milliseconds: -1,
|
||||
}
|
||||
}
|
||||
fn speed_set(&mut self, _speed: i32) -> i32 {
|
||||
-405
|
||||
}
|
||||
fn close(&mut self) {}
|
||||
fn drive_model(&self) -> &str {
|
||||
"panic drive"
|
||||
}
|
||||
fn bigendianp(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
fn set_bigendianp(&mut self, _value: i32) {}
|
||||
fn nsectors(&self) -> i64 {
|
||||
1
|
||||
}
|
||||
fn set_nsectors(&mut self, _value: i64) {}
|
||||
fn interface(&self) -> InterfaceKind {
|
||||
InterfaceKind::SgIo
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn c_api_catches_panics() {
|
||||
unsafe {
|
||||
let d = make_drive(
|
||||
"panic",
|
||||
None,
|
||||
Box::new(PanicDrive {
|
||||
toc: DiscToc::default(),
|
||||
}),
|
||||
);
|
||||
assert!(!d.is_null());
|
||||
assert_eq!(cdda_open(d), -100);
|
||||
assert_eq!(cdda_close(d), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user