#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#endif
#include <cdio/cdio.h>
#include <cdio/cd_types.h>
#include <cdio/logging.h>
#include "cdio_private.h"
#include <cdio/util.h>
#include <cdio/mmc_cmds.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_LINUX_MAJOR_H
#include <linux/major.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#define CDIO_DRIVER_UNINIT -1
int CdIo_last_driver = CDIO_DRIVER_UNINIT;
#ifdef HAVE_AIX_CDROM
const driver_id_t cdio_os_driver = DRIVER_AIX;
#elif defined(HAVE_FREEBSD_CDROM)
const driver_id_t cdio_os_driver = DRIVER_FREEBSD;
#elif defined(HAVE_LINUX_CDROM)
const driver_id_t cdio_os_driver = DRIVER_LINUX;
#elif defined(HAVE_NETBSD_CDROM)
const driver_id_t cdio_os_driver = DRIVER_NETBSD;
#elif defined(HAVE_DARWIN_CDROM)
const driver_id_t cdio_os_driver = DRIVER_OSX;
#elif defined(HAVE_SOLARIS_CDROM)
const driver_id_t cdio_os_driver = DRIVER_SOLARIS;
#elif defined(HAVE_WIN32_CDROM)
const driver_id_t cdio_os_driver = DRIVER_WIN32;
#else
const driver_id_t cdio_os_driver = DRIVER_UNKNOWN;
#endif
cdio_drive_cap_misc_t debug_cdio_drive_cap_misc;
cdio_drive_cap_read_t debug_cdio_drive_cap_read_t;
cdio_drive_cap_write_t debug_drive_cap_write_t;
cdio_mmc_hw_len_t debug_cdio_mmc_hw_len;
cdio_src_category_mask_t debug_cdio_src_category_mask;
static bool
cdio_have_false(void)
{
return false;
}
CdIo_driver_t CdIo_all_drivers[] = {
{DRIVER_UNKNOWN,
0,
"Unknown",
"No driver",
&cdio_have_false,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
{DRIVER_AIX,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"AIX",
"AIX SCSI driver",
&cdio_have_aix,
&cdio_open_aix,
&cdio_open_am_aix,
&cdio_get_default_device_aix,
&cdio_is_device_generic,
&cdio_get_devices_aix,
NULL
},
{DRIVER_FREEBSD,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"FreeBSD",
"FreeBSD driver",
&cdio_have_freebsd,
&cdio_open_freebsd,
&cdio_open_am_freebsd,
&cdio_get_default_device_freebsd,
&cdio_is_device_generic,
&cdio_get_devices_freebsd,
&close_tray_freebsd
},
{DRIVER_NETBSD,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"NetBSD",
"NetBSD driver",
&cdio_have_netbsd,
&cdio_open_netbsd,
&cdio_open_am_netbsd,
&cdio_get_default_device_netbsd,
&cdio_is_device_generic,
&cdio_get_devices_netbsd,
&close_tray_netbsd
},
{DRIVER_LINUX,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK,
"GNU/Linux",
"GNU/Linux ioctl and MMC driver",
&cdio_have_linux,
&cdio_open_linux,
&cdio_open_am_linux,
&cdio_get_default_device_linux,
&cdio_is_device_generic,
&cdio_get_devices_linux,
&close_tray_linux
},
{DRIVER_SOLARIS,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"Solaris",
"Solaris ATAPI and SCSI driver",
&cdio_have_solaris,
&cdio_open_solaris,
&cdio_open_am_solaris,
&cdio_get_default_device_solaris,
&cdio_is_device_generic,
&cdio_get_devices_solaris,
&close_tray_solaris
},
{DRIVER_OSX,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"macOS",
"Apple macOS driver",
&cdio_have_osx,
&cdio_open_osx,
&cdio_open_am_osx,
&cdio_get_default_device_osx,
&cdio_is_device_generic,
&cdio_get_devices_osx,
&close_tray_osx
},
{DRIVER_WIN32,
CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
"WIN32",
"MS Windows ASPI and ioctl driver",
&cdio_have_win32,
&cdio_open_win32,
&cdio_open_am_win32,
&cdio_get_default_device_win32,
&cdio_is_device_win32,
&cdio_get_devices_win32,
&close_tray_win32
},
{DRIVER_CDRDAO,
CDIO_SRC_IS_DISK_IMAGE_MASK,
"CDRDAO",
"cdrdao (TOC) disk image driver",
&cdio_have_cdrdao,
&cdio_open_cdrdao,
&cdio_open_am_cdrdao,
&cdio_get_default_device_cdrdao,
NULL,
&cdio_get_devices_cdrdao,
NULL
},
{DRIVER_BINCUE,
CDIO_SRC_IS_DISK_IMAGE_MASK,
"BIN/CUE",
"bin/cuesheet disk image driver",
&cdio_have_bincue,
&cdio_open_bincue,
&cdio_open_am_bincue,
&cdio_get_default_device_bincue,
NULL,
&cdio_get_devices_bincue,
NULL
},
{DRIVER_NRG,
CDIO_SRC_IS_DISK_IMAGE_MASK,
"NRG",
"Nero NRG disk image driver",
&cdio_have_nrg,
&cdio_open_nrg,
&cdio_open_am_nrg,
&cdio_get_default_device_nrg,
NULL,
&cdio_get_devices_nrg,
NULL
}
};
CdIo_driver_t CdIo_driver[sizeof(CdIo_all_drivers)/sizeof(CdIo_all_drivers[0])-1] = {
{0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} };
const driver_id_t cdio_drivers[] = {
DRIVER_AIX,
DRIVER_FREEBSD,
DRIVER_NETBSD,
DRIVER_LINUX,
DRIVER_SOLARIS,
DRIVER_OSX,
DRIVER_WIN32,
DRIVER_CDRDAO,
DRIVER_BINCUE,
DRIVER_NRG,
DRIVER_UNKNOWN
};
const driver_id_t cdio_device_drivers[] = {
DRIVER_AIX,
DRIVER_FREEBSD,
DRIVER_NETBSD,
DRIVER_LINUX,
DRIVER_SOLARIS,
DRIVER_OSX,
DRIVER_WIN32,
DRIVER_UNKNOWN
};
const char *
cdio_driver_errmsg(driver_return_code_t drc)
{
switch(drc) {
case DRIVER_OP_SUCCESS:
return "driver operation was successful";
case DRIVER_OP_ERROR:
return "driver I/O error";
case DRIVER_OP_UNSUPPORTED:
return "driver operation not supported";
case DRIVER_OP_UNINIT:
return "driver not initialized";
case DRIVER_OP_NOT_PERMITTED:
return "driver operation not permitted";
case DRIVER_OP_BAD_PARAMETER:
return "bad parameter passed";
case DRIVER_OP_BAD_POINTER:
return "bad pointer to memory area";
case DRIVER_OP_NO_DRIVER:
return "driver not available";
default:
return "unknown or bad driver return status";
}
}
static CdIo *
scan_for_driver(const driver_id_t drivers[],
const char *psz_source, const char *access_mode)
{
const driver_id_t *p_driver_id;
for (p_driver_id=drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
cdio_debug("Trying driver %s",
cdio_get_driver_name_from_id(*p_driver_id));
if ((*CdIo_all_drivers[*p_driver_id].have_driver)()) {
CdIo *ret=
(*CdIo_all_drivers[*p_driver_id].driver_open_am)(psz_source, access_mode);
if (ret != NULL) {
ret->driver_id = *p_driver_id;
cdio_info("found driver %s", cdio_get_driver_name_from_id(*p_driver_id));
return ret;
}
}
}
return NULL;
}
const char *
cdio_driver_describe(driver_id_t driver_id)
{
return CdIo_all_drivers[driver_id].describe;
}
bool
cdio_init(void)
{
CdIo_driver_t *all_dp;
CdIo_driver_t *dp = CdIo_driver;
const driver_id_t *p_driver_id;
if (CdIo_last_driver != CDIO_DRIVER_UNINIT) {
cdio_warn ("Init routine called more than once.");
return false;
}
for (p_driver_id=cdio_drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
all_dp = &CdIo_all_drivers[*p_driver_id];
if ((*CdIo_all_drivers[*p_driver_id].have_driver)()) {
*dp++ = *all_dp;
CdIo_last_driver++;
}
}
return true;
}
void
cdio_destroy (CdIo_t *p_cdio)
{
CdIo_last_driver = CDIO_DRIVER_UNINIT;
if (p_cdio == NULL) return;
if (p_cdio->op.free != NULL && p_cdio->env)
p_cdio->op.free (p_cdio->env);
p_cdio->env = NULL;
free (p_cdio);
}
driver_return_code_t
cdio_close_tray (const char *psz_orig_drive, driver_id_t
*p_driver_id)
{
driver_id_t temp_driver_id = DRIVER_DEVICE;
char *psz_drive;
driver_return_code_t drc;
if (!p_driver_id) p_driver_id = &temp_driver_id;
if (!psz_orig_drive || !*psz_orig_drive)
psz_drive = cdio_get_default_device_driver(p_driver_id);
else
psz_drive = strdup(psz_orig_drive);
if (DRIVER_UNKNOWN == *p_driver_id || DRIVER_DEVICE == *p_driver_id) {
const driver_id_t *_p_driver_id =
(DRIVER_DEVICE == *p_driver_id)?cdio_device_drivers:cdio_drivers;
p_driver_id = (driver_id_t *)_p_driver_id;
for ( ; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
*CdIo_all_drivers[*p_driver_id].close_tray ) {
drc = (*CdIo_all_drivers[*p_driver_id].close_tray)(psz_drive);
free(psz_drive);
return drc;
}
}
free(psz_drive);
return DRIVER_OP_UNSUPPORTED;
}
if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
*CdIo_all_drivers[*p_driver_id].close_tray ) {
drc = (*CdIo_all_drivers[*p_driver_id].close_tray)(psz_drive);
free(psz_drive);
return drc;
}
free(psz_drive);
return DRIVER_OP_UNSUPPORTED;
}
driver_return_code_t
cdio_eject_media (CdIo_t **pp_cdio)
{
if ((pp_cdio == NULL) || (*pp_cdio == NULL)) return DRIVER_OP_UNINIT;
if ((*pp_cdio)->op.eject_media) {
int ret = (*pp_cdio)->op.eject_media ((*pp_cdio)->env);
if (0 == ret) {
cdio_destroy(*pp_cdio);
*pp_cdio = NULL;
}
return ret;
} else {
cdio_destroy(*pp_cdio);
*pp_cdio = NULL;
return DRIVER_OP_UNSUPPORTED;
}
}
driver_return_code_t
cdio_eject_media_drive (const char *psz_drive)
{
#ifdef HAVE_LINUX_CDROM
CdIo_t *p_cdio = cdio_open_am_linux(psz_drive, "MMC_RDWR");
#else
CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_DEVICE);
#endif
if (p_cdio) {
driver_return_code_t rc;
rc = cdio_eject_media(&p_cdio);
cdio_destroy(p_cdio);
return rc;
} else {
return DRIVER_OP_UNINIT;
}
}
void
cdio_free_device_list (char * ppsz_device_list[])
{
char **ppsz_device_list_save=ppsz_device_list;
if (!ppsz_device_list) return;
for ( ; NULL != *ppsz_device_list ; ppsz_device_list++ ) {
free(*ppsz_device_list);
*ppsz_device_list = NULL;
}
CDIO_FREE_IF_NOT_NULL(ppsz_device_list_save);
}
char *
cdio_get_default_device (const CdIo_t *p_cdio)
{
if (p_cdio == NULL) {
const driver_id_t *p_driver_id;
for (p_driver_id=cdio_drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
*CdIo_all_drivers[*p_driver_id].get_default_device ) {
return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
}
}
return NULL;
}
if (p_cdio->op.get_default_device) {
return p_cdio->op.get_default_device ();
} else {
return NULL;
}
}
char *
cdio_get_default_device_driver ( driver_id_t *p_driver_id)
{
if (DRIVER_UNKNOWN == *p_driver_id || DRIVER_DEVICE == *p_driver_id) {
const driver_id_t *p_driver_id_try =
(DRIVER_DEVICE == *p_driver_id)?cdio_device_drivers:cdio_drivers;
for ( ; *p_driver_id_try!=DRIVER_UNKNOWN; p_driver_id_try++) {
if ( (*CdIo_all_drivers[*p_driver_id_try].have_driver)() &&
*CdIo_all_drivers[*p_driver_id_try].get_default_device ) {
*p_driver_id = *p_driver_id_try;
return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
}
}
return NULL;
}
if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
*CdIo_all_drivers[*p_driver_id].get_default_device ) {
return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
}
return NULL;
}
int
cdio_get_device_fd (CdIo_t *p_cdio)
{
if (p_cdio == NULL) {
return DRIVER_OP_UNINIT;
} else if (p_cdio->op.get_device_fd == NULL) {
return DRIVER_OP_UNSUPPORTED;
} else {
return p_cdio->op.get_device_fd (p_cdio->env);
}
}
char **
cdio_get_devices (driver_id_t driver_id)
{
driver_id_t driver_id_temp = driver_id;
return cdio_get_devices_ret (&driver_id_temp);
}
char **
cdio_get_devices_ret ( driver_id_t *p_driver_id)
{
CdIo_t *p_cdio;
switch (*p_driver_id) {
case DRIVER_DEVICE:
p_cdio = scan_for_driver(cdio_device_drivers, NULL, NULL);
*p_driver_id = cdio_get_driver_id(p_cdio);
break;
case DRIVER_UNKNOWN:
p_cdio = scan_for_driver(cdio_drivers, NULL, NULL);
*p_driver_id = cdio_get_driver_id(p_cdio);
break;
default:
return (*CdIo_all_drivers[*p_driver_id].get_devices)();
}
if (p_cdio == NULL) return NULL;
if (p_cdio->op.get_devices) {
char **devices = p_cdio->op.get_devices ();
cdio_destroy(p_cdio);
return devices;
} else {
return NULL;
}
}
char **
cdio_get_devices_with_cap ( char* search_devices[],
cdio_fs_anal_t capabilities, bool any)
{
driver_id_t p_driver_id;
return cdio_get_devices_with_cap_ret (search_devices, capabilities, any,
&p_driver_id);
}
char **
cdio_get_devices_with_cap_ret ( char* search_devices[],
cdio_fs_anal_t need_cap, bool b_any,
driver_id_t *p_driver_id)
{
char **ppsz_drives=search_devices;
char **ppsz_drives_ret=NULL;
unsigned int i_drives=0;
bool b_free_ppsz_drives = false;
*p_driver_id = DRIVER_DEVICE;
if (!ppsz_drives) {
ppsz_drives=cdio_get_devices_ret(p_driver_id);
b_free_ppsz_drives = true;
}
if (!ppsz_drives) return NULL;
if (need_cap == CDIO_FS_MATCH_ALL) {
char **d = ppsz_drives;
for( ; *d != NULL; d++ ) {
cdio_add_device_list(&ppsz_drives_ret, *d, &i_drives);
}
} else {
const cdio_fs_anal_t need_fs = CDIO_FSTYPE(need_cap);
char **d = ppsz_drives;
for( ; *d != NULL; d++ ) {
CdIo_t *p_cdio = cdio_open(*d, *p_driver_id);
if (NULL != p_cdio) {
track_t i_first_track = cdio_get_first_track_num(p_cdio);
cdio_iso_analysis_t cdio_iso_analysis;
if (CDIO_INVALID_TRACK != i_first_track) {
const cdio_fs_anal_t got_cap =
cdio_guess_cd_type(p_cdio, 0, i_first_track, &cdio_iso_analysis);
if ( CDIO_FS_UNKNOWN == need_fs || 0 == need_fs
|| (CDIO_FSTYPE(got_cap) == need_fs) ) {
const cdio_fs_anal_t need_anal = need_cap & ~CDIO_FS_MASK;
const cdio_fs_anal_t got_anal = got_cap & ~CDIO_FS_MASK;
const bool b_match = !need_anal
|| (b_any
? (got_anal & need_anal) != 0
: (got_anal & need_anal) == need_anal);
if (b_match)
cdio_add_device_list(&ppsz_drives_ret, *d, &i_drives);
}
}
cdio_destroy(p_cdio);
}
}
}
cdio_add_device_list(&ppsz_drives_ret, NULL, &i_drives);
if (b_free_ppsz_drives) {
cdio_free_device_list(ppsz_drives);
}
return ppsz_drives_ret;
}
void
cdio_get_drive_cap (const CdIo_t *p_cdio,
cdio_drive_read_cap_t *p_read_cap,
cdio_drive_write_cap_t *p_write_cap,
cdio_drive_misc_cap_t *p_misc_cap)
{
*p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
if (p_cdio && p_cdio->op.get_drive_cap) {
p_cdio->op.get_drive_cap(p_cdio->env, p_read_cap, p_write_cap, p_misc_cap);
}
}
void
cdio_get_drive_cap_dev (const char *device,
cdio_drive_read_cap_t *p_read_cap,
cdio_drive_write_cap_t *p_write_cap,
cdio_drive_misc_cap_t *p_misc_cap)
{
CdIo_t *cdio=scan_for_driver(cdio_drivers, device, NULL);
if (cdio) {
cdio_get_drive_cap(cdio, p_read_cap, p_write_cap, p_misc_cap);
cdio_destroy(cdio);
} else {
*p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
}
}
const char *
cdio_get_driver_name (const CdIo_t *p_cdio)
{
if (NULL==p_cdio) return NULL;
return cdio_get_driver_name_from_id(p_cdio->driver_id);
}
const char *
cdio_get_driver_name_from_id (driver_id_t driver_id)
{
return CdIo_all_drivers[driver_id].name;
}
driver_id_t
cdio_get_driver_id (const CdIo_t *p_cdio)
{
if (!p_cdio) return DRIVER_UNKNOWN;
return p_cdio->driver_id;
}
bool
cdio_get_hwinfo (const CdIo_t *p_cdio, cdio_hwinfo_t *hw_info)
{
if (!p_cdio) return false;
if (p_cdio->op.get_hwinfo) {
return p_cdio->op.get_hwinfo (p_cdio, hw_info);
} else {
return mmc_get_hwinfo(p_cdio, hw_info);
}
}
driver_return_code_t cdio_get_last_session (CdIo_t *p_cdio,
lsn_t *i_last_session)
{
if (!p_cdio) return DRIVER_OP_UNINIT;
if (p_cdio->op.get_last_session)
return p_cdio->op.get_last_session(p_cdio->env, i_last_session);
return DRIVER_OP_UNSUPPORTED;
}
int
cdio_get_media_changed(CdIo_t *p_cdio)
{
if (!p_cdio) return DRIVER_OP_UNINIT;
if (p_cdio->op.get_media_changed)
return p_cdio->op.get_media_changed(p_cdio->env);
return DRIVER_OP_UNSUPPORTED;
}
bool_3way_t
cdio_have_atapi(CdIo_t *p_cdio)
{
bool_3way_t i_status;
if (!p_cdio) return nope;
i_status = mmc_have_interface(p_cdio, CDIO_MMC_FEATURE_INTERFACE_ATAPI);
if (dunno != i_status) return i_status;
{
uint8_t buf[22];
if (DRIVER_OP_SUCCESS == mmc_mode_sense(p_cdio, buf, sizeof(buf),
CDIO_MMC_CAPABILITIES_PAGE) ) {
uint8_t *b = buf;
b+=b[3]+4;
if( CDIO_MMC_CAPABILITIES_PAGE == (b[0]&0x3F) ) {
return yep;
}
}
}
#ifdef HAVE_LINUX_MAJOR_H
{
struct stat st;
generic_img_private_t *p_env = p_cdio->env;
if ( 0 == lstat(p_env->source_name, &st) ) {
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
int drive_type=(int)(st.st_rdev>>8);
switch (drive_type) {
case IDE0_MAJOR:
case IDE1_MAJOR:
case IDE2_MAJOR:
case IDE3_MAJOR:
return yep;
break;
case CDU31A_CDROM_MAJOR:
case CDU535_CDROM_MAJOR:
case MATSUSHITA_CDROM_MAJOR:
case MATSUSHITA_CDROM2_MAJOR:
case MATSUSHITA_CDROM3_MAJOR:
case MATSUSHITA_CDROM4_MAJOR:
case SANYO_CDROM_MAJOR:
case MITSUMI_CDROM_MAJOR:
case MITSUMI_X_CDROM_MAJOR:
case OPTICS_CDROM_MAJOR:
case AZTECH_CDROM_MAJOR:
case GOLDSTAR_CDROM_MAJOR:
case CM206_CDROM_MAJOR:
case SCSI_CDROM_MAJOR:
case SCSI_GENERIC_MAJOR:
return nope;
break;
default:
return dunno;
}
}
}
}
#endif
return dunno;
}
bool
cdio_have_driver(driver_id_t driver_id)
{
if (driver_id < 0 || driver_id >= sizeof(CdIo_all_drivers)/sizeof(CdIo_all_drivers[0]))
return false;
return (*CdIo_all_drivers[driver_id].have_driver)();
}
bool
cdio_is_device(const char *psz_source, driver_id_t driver_id)
{
if (DRIVER_UNKNOWN == driver_id || DRIVER_DEVICE == driver_id) {
const driver_id_t *p_driver_id = (DRIVER_DEVICE == driver_id)?cdio_device_drivers:cdio_drivers;
for ( ; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
CdIo_all_drivers[*p_driver_id].is_device ) {
return (*CdIo_all_drivers[*p_driver_id].is_device)(psz_source);
}
}
}
if (driver_id < DRIVER_UNKNOWN || driver_id >= DRIVER_DEVICE ||
CdIo_all_drivers[driver_id].is_device == NULL)
return false;
return (*CdIo_all_drivers[driver_id].is_device)(psz_source);
}
CdIo_t *
cdio_open (const char *orig_source_name, driver_id_t driver_id)
{
return cdio_open_am(orig_source_name, driver_id, NULL);
}
CdIo_t *
cdio_open_am (const char *psz_orig_source, driver_id_t driver_id,
const char *psz_access_mode)
{
char *psz_source;
if (CdIo_last_driver == -1) cdio_init();
if (!psz_orig_source || !*psz_orig_source)
psz_source = cdio_get_default_device(NULL);
else
psz_source = strdup(psz_orig_source);
switch (driver_id) {
case DRIVER_UNKNOWN:
{
CdIo_t *p_cdio=scan_for_driver(cdio_drivers,
psz_source, psz_access_mode);
free(psz_source);
return p_cdio;
}
case DRIVER_DEVICE:
{
CdIo_t *ret = cdio_open_am_cd(psz_source, psz_access_mode);
free(psz_source);
return ret;
}
break;
case DRIVER_AIX:
case DRIVER_FREEBSD:
case DRIVER_LINUX:
case DRIVER_NETBSD:
case DRIVER_SOLARIS:
case DRIVER_WIN32:
case DRIVER_OSX:
case DRIVER_NRG:
case DRIVER_BINCUE:
case DRIVER_CDRDAO:
if ((*CdIo_all_drivers[driver_id].have_driver)()) {
CdIo_t *ret =
(*CdIo_all_drivers[driver_id].driver_open_am)(psz_source,
psz_access_mode);
if (ret) ret->driver_id = driver_id;
free(psz_source);
return ret;
}
}
free(psz_source);
return NULL;
}
CdIo_t *
cdio_open_cd (const char *psz_source)
{
return cdio_open_am_cd(psz_source, NULL);
}
CdIo_t *
cdio_open_am_cd (const char *psz_source, const char *psz_access_mode)
{
if (CdIo_last_driver == -1) cdio_init();
return scan_for_driver(cdio_device_drivers, psz_source, psz_access_mode);
}
driver_return_code_t
cdio_set_blocksize ( const CdIo_t *p_cdio, int i_blocksize )
{
if (!p_cdio) return DRIVER_OP_UNINIT;
if (!p_cdio->op.set_blocksize) return DRIVER_OP_UNSUPPORTED;
return p_cdio->op.set_blocksize(p_cdio->env, i_blocksize);
}
driver_return_code_t
cdio_set_speed (const CdIo_t *p_cdio, int i_speed)
{
if (!p_cdio) return DRIVER_OP_UNINIT;
if (!p_cdio->op.set_speed) return DRIVER_OP_UNSUPPORTED;
return p_cdio->op.set_speed(p_cdio->env, i_speed);
}