📄 _cdio_osx.c
字号:
}/*! Return the starting LSN track number i_track in obj. Track numbers start at 1. The "leadout" track is specified either by using i_track LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry.*/static lsn_tget_track_lba_osx(void *p_user_data, track_t i_track){ _img_private_t *p_env = p_user_data; if (!p_env->gen.toc_init) read_toc_osx (p_env) ; if (!p_env->gen.toc_init) return CDIO_INVALID_LSN; if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->i_last_track+1; if (i_track > p_env->i_last_track + 1 || i_track < p_env->gen.i_first_track) { return CDIO_INVALID_LSN; } else { return p_env->pp_lba[i_track - p_env->gen.i_first_track]; }}/*! Eject media . Return 1 if successful, 0 otherwise. The only way to cleanly unmount the disc under MacOS X is to use the 'disktool' command line utility. It uses the non-public Disk Arbitration API, which can not be used by Cocoa or Carbon applications. */static int _eject_media_osx (void *user_data) { _img_private_t *p_env = user_data; FILE *p_eject; char *psz_disk; char sz_cmd[32]; if( ( psz_disk = (char *)strstr( p_env->gen.source_name, "disk" ) ) != NULL && strlen( psz_disk ) > 4 ) {#define EJECT_CMD "/usr/sbin/hdiutil eject %s" snprintf( sz_cmd, sizeof(sz_cmd), EJECT_CMD, psz_disk );#undef EJECT_CMD if( ( p_eject = popen( sz_cmd, "r" ) ) != NULL ) { char psz_result[0x200]; int i_ret = fread( psz_result, 1, sizeof(psz_result) - 1, p_eject ); if( i_ret == 0 && ferror( p_eject ) != 0 ) { pclose( p_eject ); return 0; } pclose( p_eject ); psz_result[ i_ret ] = 0; if( strstr( psz_result, "Disk Ejected" ) != NULL ) { return 1; } } } return 0;}/*! Return the size of the CD in logical block address (LBA) units. */static uint32_t _stat_size_osx (void *user_data){ return get_track_lba_osx(user_data, CDIO_CDROM_LEADOUT_TRACK);}/*! Return the value associated with the key "arg".*/static const char *_get_arg_osx (void *user_data, const char key[]){ _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { return p_env->gen.source_name; } else if (!strcmp (key, "access-mode")) { switch (p_env->access_mode) { case _AM_OSX: return "OS X"; case _AM_NONE: return "no access method"; } } return NULL;}/*! Return the media catalog number MCN. */static char *get_mcn_osx (const void *user_data) { const _img_private_t *p_env = user_data; dk_cd_read_mcn_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); if( ioctl( p_env->gen.fd, DKIOCCDREADMCN, &cd_read ) < 0 ) { cdio_debug( "could not read MCN, %s", strerror(errno) ); return NULL; } return strdup((char*)cd_read.mcn);}/*! Get format of track. */static track_format_tget_track_format_osx(void *user_data, track_t i_track) { _img_private_t *p_env = user_data; dk_cd_read_track_info_t cd_read; CDTrackInfo a_track; if (!p_env->gen.toc_init) read_toc_osx (p_env) ; if (i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track) return TRACK_FORMAT_ERROR; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.address = i_track; cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber; cd_read.buffer = &a_track; cd_read.bufferLength = sizeof(CDTrackInfo); if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) { cdio_warn( "could not read trackinfo for track %d", i_track ); return TRACK_FORMAT_ERROR; } cdio_debug( "%d: trackinfo trackMode: %x dataMode: %x", i_track, a_track.trackMode, a_track.dataMode ); if (a_track.trackMode == CDIO_CDROM_DATA_TRACK) { if (a_track.dataMode == CDROM_CDI_TRACK) { return TRACK_FORMAT_CDI; } else if (a_track.dataMode == CDROM_XA_TRACK) { return TRACK_FORMAT_XA; } else { return TRACK_FORMAT_DATA; } } else { return TRACK_FORMAT_AUDIO; }}/*! Return true if we have XA data (green, mode2 form1) or XA data (green, mode2 form2). That is track begins: sync - header - subheader 12 4 - 8 FIXME: there's gotta be a better design for this and get_track_format?*/static boolget_track_green_osx(void *user_data, track_t i_track) { _img_private_t *p_env = user_data; CDTrackInfo a_track; if (!p_env->gen.toc_init) read_toc_osx (p_env) ; if ( i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track ) return false; else { dk_cd_read_track_info_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.address = i_track; cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber; cd_read.buffer = &a_track; cd_read.bufferLength = sizeof(CDTrackInfo); if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) { cdio_warn( "could not read trackinfo for track %d", i_track ); return false; } return ((a_track.trackMode & CDIO_CDROM_DATA_TRACK) != 0); }}#endif /* HAVE_DARWIN_CDROM *//*! Return a string containing the default CD device if none is specified. */char **cdio_get_devices_osx(void){#ifndef HAVE_DARWIN_CDROM return NULL;#else io_object_t next_media; mach_port_t master_port; kern_return_t kern_result; io_iterator_t media_iterator; CFMutableDictionaryRef classes_to_match; char **drives = NULL; unsigned int num_drives=0; kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); if( kern_result != KERN_SUCCESS ) { return( NULL ); } classes_to_match = IOServiceMatching( kIOCDMediaClass ); if( classes_to_match == NULL ) { return( NULL ); } CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue ); kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, &media_iterator ); if( kern_result != KERN_SUCCESS ) { return( NULL ); } next_media = IOIteratorNext( media_iterator ); if( next_media != 0 ) { char psz_buf[0x32]; size_t dev_path_length; CFTypeRef str_bsd_path; do { str_bsd_path = IORegistryEntryCreateCFProperty( next_media, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); if( str_bsd_path == NULL ) { IOObjectRelease( next_media ); continue; } snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); dev_path_length = strlen( psz_buf ); if( CFStringGetCString( str_bsd_path, (char*)&psz_buf + dev_path_length, sizeof(psz_buf) - dev_path_length, kCFStringEncodingASCII ) ) { CFRelease( str_bsd_path ); IOObjectRelease( next_media ); IOObjectRelease( media_iterator ); cdio_add_device_list(&drives, strdup(psz_buf), &num_drives); } CFRelease( str_bsd_path ); IOObjectRelease( next_media ); } while( ( next_media = IOIteratorNext( media_iterator ) ) != 0 ); } IOObjectRelease( media_iterator ); cdio_add_device_list(&drives, NULL, &num_drives); return drives;#endif /* HAVE_DARWIN_CDROM */}/*! Return a string containing the default CD device if none is specified. */char *cdio_get_default_device_osx(void){#ifndef HAVE_DARWIN_CDROM return NULL;#else io_object_t next_media; mach_port_t master_port; kern_return_t kern_result; io_iterator_t media_iterator; CFMutableDictionaryRef classes_to_match; kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); if( kern_result != KERN_SUCCESS ) { return( NULL ); } classes_to_match = IOServiceMatching( kIOCDMediaClass ); if( classes_to_match == NULL ) { return( NULL ); } CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue ); kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, &media_iterator ); if( kern_result != KERN_SUCCESS ) { return( NULL ); } next_media = IOIteratorNext( media_iterator ); if( next_media != 0 ) { char psz_buf[0x32]; size_t dev_path_length; CFTypeRef str_bsd_path; do { str_bsd_path = IORegistryEntryCreateCFProperty( next_media, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); if( str_bsd_path == NULL ) { IOObjectRelease( next_media ); continue; } snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); dev_path_length = strlen( psz_buf ); if( CFStringGetCString( str_bsd_path, (char*)&psz_buf + dev_path_length, sizeof(psz_buf) - dev_path_length, kCFStringEncodingASCII ) ) { CFRelease( str_bsd_path ); IOObjectRelease( next_media ); IOObjectRelease( media_iterator ); return strdup( psz_buf ); } CFRelease( str_bsd_path ); IOObjectRelease( next_media ); } while( ( next_media = IOIteratorNext( media_iterator ) ) != 0 ); } IOObjectRelease( media_iterator ); return NULL;#endif /* HAVE_DARWIN_CDROM */}/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */CdIo *cdio_open_am_osx (const char *psz_source_name, const char *psz_access_mode){ if (psz_access_mode != NULL) cdio_warn ("there is only one access mode for OS X. Arg %s ignored", psz_access_mode); return cdio_open_osx(psz_source_name);}/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */CdIo *cdio_open_osx (const char *psz_orig_source){#ifdef HAVE_DARWIN_CDROM CdIo *ret; _img_private_t *_data; char *psz_source; cdio_funcs _funcs = { .eject_media = _eject_media_osx, .free = _free_osx, .get_arg = _get_arg_osx, .get_cdtext = get_cdtext_osx, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, .get_discmode = get_discmode_osx, .get_drive_cap = get_drive_cap_osx, .get_first_track_num= get_first_track_num_generic, .get_hwinfo = get_hwinfo_osx, .get_mcn = get_mcn_osx, .get_num_tracks = get_num_tracks_generic, .get_track_format = get_track_format_osx, .get_track_green = get_track_green_osx, .get_track_lba = get_track_lba_osx, .get_track_msf = NULL, .lseek = cdio_generic_lseek, .read = cdio_generic_read, .read_audio_sectors = _get_read_audio_sectors_osx, .read_mode1_sector = _get_read_mode1_sector_osx, .read_mode1_sectors = _get_read_mode1_sectors_osx, .read_mode2_sector = _get_read_mode2_sector_osx, .read_mode2_sectors = _get_read_mode2_sectors_osx, .read_toc = read_toc_osx, .run_scsi_mmc_cmd = run_scsi_cmd_osx, .set_arg = _set_arg_osx, .stat_size = _stat_size_osx }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_OSX; _data->MediaClass_service = 0; _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { psz_source=cdio_get_default_device_osx(); if (NULL == psz_source) return NULL; _set_arg_osx(_data, "source", psz_source); free(psz_source); } else { if (cdio_is_device_generic(psz_orig_source)) _set_arg_osx(_data, "source", psz_orig_source); else { /* The below would be okay if all device drivers worked this way. */#if 0 cdio_info ("source %s is a not a device", psz_orig_source);#endif return NULL; } } ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; if (cdio_generic_init(_data) && init_osx(_data)) return ret; else { cdio_generic_free (_data); return NULL; } #else return NULL;#endif /* HAVE_DARWIN_CDROM */}boolcdio_have_osx (void){#ifdef HAVE_DARWIN_CDROM return true;#else return false;#endif /* HAVE_DARWIN_CDROM */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -