📄 cdio.c
字号:
/* $Id: cdio.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <errno.h>#include <string.h>#include "cdio_assert.h"#include <cdio/cdio.h>#include <cdio/cd_types.h>#include <cdio/util.h>#include <cdio/logging.h>#include "cdio_private.h"static const char _rcsid[] = "$Id: cdio.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $";const char *track_format2str[6] = { "audio", "CD-i", "XA", "data", "PSX", "error" };/* Must match discmode enumeration */const char *discmode2str[] = { "CD-DA", "CD-DATA Form 1", "CD DATA Form 2", "CD-ROM Mixed", "DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW", "DVD+R", "DVD+RW", "Unknown/unclassified DVD", "No information", "Error in getting information"};/* The below array gives of the drivers that are currently available for on a particular host. */CdIo_driver_t CdIo_driver[CDIO_MAX_DRIVER] = { {0} };/* The last valid entry of Cdio_driver. -1 or (CDIO_DRIVER_UNINIT) means uninitialzed. -2 means some sort of error.*/#define CDIO_DRIVER_UNINIT -1int CdIo_last_driver = CDIO_DRIVER_UNINIT;#ifdef HAVE_BSDI_CDROMconst driver_id_t cdio_os_driver = DRIVER_BSDI;#elif HAVE_FREEBSD_CDROMconst driver_id_t cdio_os_driver = DRIVER_FREEBSD;#elif HAVE_LINUX_CDROMconst driver_id_t cdio_os_driver = DRIVER_LINUX;#elif HAVE_DARWIN_CDROMconst driver_id_t cdio_os_driver = DRIVER_OSX;#elif HAVE_DARWIN_SOLARISconst driver_id_t cdio_os_driver = DRIVER_SOLARIS;#elif HAVE_DARWIN_WIN32const driver_id_t cdio_os_driver = DRIVER_WIN32;#else const driver_id_t cdio_os_driver = DRIVER_UNKNOWN;#endifstatic bool cdio_have_false(void){ return false;}/* The below array gives all drivers that can possibly appear. on a particular host. */CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { {DRIVER_UNKNOWN, 0, "Unknown", "No driver", &cdio_have_false, NULL, NULL, NULL, NULL, NULL }, {DRIVER_BSDI, CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, "BSDI", "BSDI ATAPI and SCSI driver", &cdio_have_bsdi, &cdio_open_bsdi, &cdio_open_am_bsdi, &cdio_get_default_device_bsdi, &cdio_is_device_generic, &cdio_get_devices_bsdi }, {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, NULL }, {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 }, {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 }, {DRIVER_OSX, CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, "OS X", "Apple Darwin OS X driver", &cdio_have_osx, &cdio_open_osx, &cdio_open_am_osx, &cdio_get_default_device_osx, &cdio_is_device_generic, &cdio_get_devices_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 }, {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 }, {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 }, {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 }};static CdIo *scan_for_driver(driver_id_t start, driver_id_t end, const char *psz_source, const char *access_mode) { driver_id_t driver_id; for (driver_id=start; driver_id<=end; driver_id++) { if ((*CdIo_all_drivers[driver_id].have_driver)()) { CdIo *ret= (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, access_mode); if (ret != NULL) { ret->driver_id = driver_id; return ret; } } } return NULL;}const char *cdio_driver_describe(driver_id_t driver_id){ return CdIo_all_drivers[driver_id].describe;}/*! Eject media in CD drive if there is a routine to do so. Return 0 if success and 1 for failure, and 2 if no routine. If the CD is ejected *obj is freed and obj set to NULL. */intcdio_eject_media (CdIo **obj){ if ((obj == NULL) || (*obj == NULL)) return 1; if ((*obj)->op.eject_media) { int ret = (*obj)->op.eject_media ((*obj)->env); if (0 == ret) { cdio_destroy(*obj); *obj = NULL; } return ret; } else { cdio_destroy(*obj); *obj = NULL; return 2; }}/*! Free device list returned by cdio_get_devices or cdio_get_devices_with_cap.*/void cdio_free_device_list (char * device_list[]) { if (NULL == device_list) return; for ( ; *device_list != NULL ; device_list++ ) free(*device_list);}/*! Return the value associatied with key. NULL is returned if obj is NULL or "key" does not exist. */const char *cdio_get_arg (const CdIo *obj, const char key[]){ if (obj == NULL) return NULL; if (obj->op.get_arg) { return obj->op.get_arg (obj->env, key); } else { return NULL; }}/*! Get cdtext information for a CdIo object . @param obj the CD object that may contain CD-TEXT information. @return the CD-TEXT object or NULL if obj is NULL or CD-TEXT information does not exist.*/const cdtext_t *cdio_get_cdtext (CdIo *obj, track_t i_track){ if (obj == NULL) return NULL; if (obj->op.get_cdtext) { return obj->op.get_cdtext (obj->env, i_track); } else { return NULL; }}/*! Return a string containing the default CD device if none is specified. if CdIo is NULL (we haven't initialized a specific device driver), then find a suitable one and return the default device for that. NULL is returned if we couldn't get a default device. */char *cdio_get_default_device (const CdIo *obj){ if (obj == NULL) { driver_id_t driver_id; /* Scan for driver */ for (driver_id=DRIVER_UNKNOWN; driver_id<=CDIO_MAX_DRIVER; driver_id++) { if ( (*CdIo_all_drivers[driver_id].have_driver)() && *CdIo_all_drivers[driver_id].get_default_device ) { return (*CdIo_all_drivers[driver_id].get_default_device)(); } } return NULL; } if (obj->op.get_default_device) { return obj->op.get_default_device (); } else { return NULL; }}/*!Return an array of device names. If you want a specific devices, dor a driver give that device, if you want hardware devices, give DRIVER_DEVICE and if you want all possible devices, image drivers and hardware drivers give DRIVER_UNKNOWN. NULL is returned if we couldn't return a list of devices.*/char **cdio_get_devices (driver_id_t driver_id){ /* Probably could get away with &driver_id below. */ driver_id_t driver_id_temp = driver_id; return cdio_get_devices_ret (&driver_id_temp);}char **cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id){ CdIo *p_cdio; switch (*p_driver_id) { /* FIXME: spit out unknown to give image drivers as well. */ case DRIVER_UNKNOWN: case DRIVER_DEVICE: p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DRIVER, 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; }}/*! Return an array of device names in search_devices that have at least the capabilities listed by cap. If search_devices is NULL, then we'll search all possible CD drives. If "any" is set false then every capability listed in the extended portion of capabilities (i.e. not the basic filesystem) must be satisified. If "any" is set true, then if any of the capabilities matches, we call that a success. To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. NULL is returned if we couldn't get a default device. It is also possible to return a non NULL but after dereferencing the the value is NULL. This also means nothing was found.*/char **cdio_get_devices_with_cap (/*out*/ 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 (/*out*/ char* search_devices[], cdio_fs_anal_t capabilities, bool any, /*out*/ driver_id_t *p_driver_id){ char **drives=search_devices; char **drives_ret=NULL; unsigned int i_drives=0; *p_driver_id = DRIVER_DEVICE; if (NULL == drives) drives=cdio_get_devices_ret(p_driver_id); if (NULL == drives) return NULL; if (capabilities == CDIO_FS_MATCH_ALL) { /* Duplicate drives into drives_ret. */ char **d = drives; for( ; *d != NULL; d++ ) { cdio_add_device_list(&drives_ret, *d, &i_drives); } } else { cdio_fs_anal_t got_fs=0; cdio_fs_anal_t need_fs = CDIO_FSTYPE(capabilities); cdio_fs_anal_t need_fs_ext; char **d = drives; need_fs_ext = capabilities & ~CDIO_FS_MASK; for( ; *d != NULL; d++ ) { CdIo *cdio = cdio_open(*d, *p_driver_id); if (NULL != cdio) { track_t first_track = cdio_get_first_track_num(cdio); cdio_iso_analysis_t cdio_iso_analysis; got_fs = cdio_guess_cd_type(cdio, 0, first_track, &cdio_iso_analysis); /* Match on fs and add */ if ( (CDIO_FS_UNKNOWN == need_fs || CDIO_FSTYPE(got_fs) == need_fs) ) { bool doit = any ? (got_fs & need_fs_ext) != 0 : (got_fs | ~need_fs_ext) == -1; if (doit) cdio_add_device_list(&drives_ret, *d, &i_drives); } cdio_destroy(cdio); } } } cdio_add_device_list(&drives_ret, NULL, &i_drives); cdio_free_device_list(drives); free(drives); return drives_ret;}/*! Get medium associated with cd_obj.*/discmode_tcdio_get_discmode (CdIo *cd_obj){ if (cd_obj == NULL) return CDIO_DISC_MODE_ERROR; if (cd_obj->op.get_discmode) { return cd_obj->op.get_discmode (cd_obj->env); } else { return CDIO_DISC_MODE_NO_INFO; }}/*! Return the the kind of drive capabilities of device. Note: string is malloc'd so caller should free() then returned string when done with it. */voidcdio_get_drive_cap (const CdIo *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){ /* This seems like a safe bet. */ *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); }}/*! Return the the kind of drive capabilities of device. Note: string is malloc'd so caller should free() then returned string when done with it. */voidcdio_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){ /* This seems like a safe bet. */ CdIo *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, 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; }}/*! Return a string containing the name of the driver in use. if CdIo is NULL (we haven't initialized a specific device driver), then return NULL.*/const char *cdio_get_driver_name (const CdIo *cdio) { if (NULL==cdio) return NULL; return CdIo_all_drivers[cdio->driver_id].name;} /*! Return the driver id. if CdIo is NULL (we haven't initialized a specific device driver), then return DRIVER_UNKNOWN. */driver_id_tcdio_get_driver_id (const CdIo *cdio) { if (NULL==cdio) return DRIVER_UNKNOWN; return cdio->driver_id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -