📄 _cdio_linux.c
字号:
return 0;}/*! Read and cache the CD's Track Table of Contents and track info. Return false if successful or true if an error.*/static boolread_toc_linux (void *p_user_data) { _img_private_t *p_env = p_user_data; int i; /* read TOC header */ if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) { cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; } p_env->gen.i_first_track = p_env->tochdr.cdth_trk0; p_env->gen.i_tracks = p_env->tochdr.cdth_trk1; /* read individual tracks */ for (i= p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) { p_env->tocent[i-p_env->gen.i_first_track].cdte_track = i; p_env->tocent[i-p_env->gen.i_first_track].cdte_format = CDROM_MSF; if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-p_env->gen.i_first_track]) == -1 ) { cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } /**** struct cdrom_msf0 *msf= &env->tocent[i-1].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); ****/ } /* read the lead-out track */ p_env->tocent[p_env->gen.i_tracks].cdte_track = CDIO_CDROM_LEADOUT_TRACK; p_env->tocent[p_env->gen.i_tracks].cdte_format = CDROM_MSF; if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[p_env->gen.i_tracks]) == -1 ) { cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", strerror(errno)); return false; } /* struct cdrom_msf0 *msf= &env->tocent[p_env->gen.i_tracks].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); */ p_env->gen.toc_init = true; return true;}/*! Run a SCSI MMC command. cdio CD structure set by cdio_open(). i_timeout time in milliseconds we will wait for the command to complete. If this value is -1, use the default time-out value. p_buf Buffer for data, both sending and receiving i_buf Size of buffer e_direction direction the transfer is to go. cdb CDB bytes. All values that are needed should be set on input. We'll figure out what the right CDB length should be. We return true if command completed successfully and false if not. */static intrun_scsi_cmd_linux( const void *p_user_data, unsigned int i_timeout_ms, unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, scsi_mmc_direction_t e_direction, unsigned int i_buf, /*in/out*/ void *p_buf ){ const _img_private_t *p_env = p_user_data; struct cdrom_generic_command cgc; memset (&cgc, 0, sizeof (struct cdrom_generic_command)); memcpy(&cgc.cmd, p_cdb, i_cdb); cgc.buflen = i_buf; cgc.buffer = p_buf; cgc.data_direction = (SCSI_MMC_DATA_READ == cgc.data_direction) ? CGC_DATA_READ : CGC_DATA_WRITE;#ifdef HAVE_LINUX_CDROM_TIMEOUT cgc.timeout = i_timeout_ms;#endif return ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc);}/*! Return the size of the CD in logical block address (LBA) units. */static uint32_t stat_size_linux (void *p_user_data){ _img_private_t *p_env = p_user_data; struct cdrom_tocentry tocent; uint32_t size; tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; tocent.cdte_format = CDROM_LBA; if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); } size = tocent.cdte_addr.lba; return size;}/*! Set the arg "key" with "value" in the source device. Currently "source" and "access-mode" are valid keys. "source" sets the source device in I/O operations "access-mode" sets the the method of CD access 0 is returned if no error was found, and nonzero if there as an error.*/static intset_arg_linux (void *p_user_data, const char key[], const char value[]){ _img_private_t *p_env = p_user_data; if (!strcmp (key, "source")) { if (!value) return -2; free (p_env->gen.source_name); p_env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { return str_to_access_mode_linux(value); } else return -1; return 0;}/* checklist: /dev/cdrom, /dev/dvd /dev/hd?, /dev/scd? /dev/sr? */static char checklist1[][40] = { {"cdrom"}, {"dvd"}, {""}};static char checklist2[][40] = { {"?a hd?"}, {"?0 scd?"}, {"?0 sr?"}, {""}};#endif /* HAVE_LINUX_CDROM *//*! Return an array of strings giving possible CD devices. */char **cdio_get_devices_linux (void){#ifndef HAVE_LINUX_CDROM return NULL;#else unsigned int i; char drive[40]; char *ret_drive; bool exists; char **drives = NULL; unsigned int num_drives=0; /* Scan the system for CD-ROM drives. */ for ( i=0; strlen(checklist1[i]) > 0; ++i ) { sprintf(drive, "/dev/%s", checklist1[i]); if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { cdio_add_device_list(&drives, drive, &num_drives); } } /* Now check the currently mounted CD drives */ if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) { cdio_add_device_list(&drives, ret_drive, &num_drives); free(ret_drive); } /* Finally check possible mountable drives in /etc/fstab */ if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) { cdio_add_device_list(&drives, ret_drive, &num_drives); free(ret_drive); } /* Scan the system for CD-ROM drives. Not always 100% reliable, so use the USE_MNTENT code above first. */ for ( i=0; strlen(checklist2[i]) > 0; ++i ) { unsigned int j; char *insert; exists = true; for ( j=checklist2[i][1]; exists; ++j ) { sprintf(drive, "/dev/%s", &checklist2[i][3]); insert = strchr(drive, '?'); if ( insert != NULL ) { *insert = j; } if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { cdio_add_device_list(&drives, drive, &num_drives); } } } cdio_add_device_list(&drives, NULL, &num_drives); return drives;#endif /*HAVE_LINUX_CDROM*/}/*! Return a string containing the default CD device. */char *cdio_get_default_device_linux(void){#ifndef HAVE_LINUX_CDROM return NULL; #else unsigned int i; char drive[40]; bool exists; char *ret_drive; /* Scan the system for CD-ROM drives. */ for ( i=0; strlen(checklist1[i]) > 0; ++i ) { sprintf(drive, "/dev/%s", checklist1[i]); if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { return strdup(drive); } } /* Now check the currently mounted CD drives */ if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) return ret_drive; /* Finally check possible mountable drives in /etc/fstab */ if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) return ret_drive; /* Scan the system for CD-ROM drives. Not always 100% reliable, so use the USE_MNTENT code above first. */ for ( i=0; strlen(checklist2[i]) > 0; ++i ) { unsigned int j; char *insert; exists = true; for ( j=checklist2[i][1]; exists; ++j ) { sprintf(drive, "/dev/%s", &checklist2[i][3]); insert = strchr(drive, '?'); if ( insert != NULL ) { *insert = j; } if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { return(strdup(drive)); } } } return NULL;#endif /*HAVE_LINUX_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_linux (const char *psz_source_name){ return cdio_open_am_linux(psz_source_name, NULL);}/*! 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_linux (const char *psz_orig_source, const char *access_mode){#ifdef HAVE_LINUX_CDROM CdIo *ret; _img_private_t *_data; char *psz_source; cdio_funcs _funcs = { .eject_media = eject_media_linux, .free = cdio_generic_free, .get_arg = get_arg_linux, .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_linux, .get_devices = cdio_get_devices_linux, .get_discmode = get_discmode_linux,#if USE_LINUX_CAP .get_drive_cap = get_drive_cap_linux,#else .get_drive_cap = scsi_mmc_get_drive_cap_generic,#endif .get_first_track_num= get_first_track_num_generic, .get_hwinfo = NULL, .get_mcn = get_mcn_linux, .get_num_tracks = get_num_tracks_generic, .get_track_format = get_track_format_linux, .get_track_green = get_track_green_linux, .get_track_lba = NULL, /* This could be implemented if need be. */ .get_track_msf = get_track_msf_linux, .lseek = cdio_generic_lseek, .read = cdio_generic_read, .read_audio_sectors = _read_audio_sectors_linux, .read_mode1_sector = _read_mode1_sector_linux, .read_mode1_sectors = _read_mode1_sectors_linux, .read_mode2_sector = _read_mode2_sector_linux, .read_mode2_sectors = _read_mode2_sectors_linux, .read_toc = read_toc_linux, .run_scsi_mmc_cmd = run_scsi_cmd_linux, .set_arg = set_arg_linux, .stat_size = stat_size_linux }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = str_to_access_mode_linux(access_mode); _data->gen.init = false; _data->gen.toc_init = false; _data->gen.fd = -1; _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source) { psz_source=cdio_get_default_device_linux(); if (NULL == psz_source) { free(_data); return NULL; } set_arg_linux(_data, "source", psz_source); free(psz_source); } else { if (cdio_is_device_generic(psz_orig_source)) set_arg_linux(_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 not a device", psz_orig_source);#endif free(_data); return NULL; } } ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; if (cdio_generic_init(_data)) { return ret; } else { cdio_generic_free (_data); return NULL; } #else return NULL;#endif /* HAVE_LINUX_CDROM */}boolcdio_have_linux (void){#ifdef HAVE_LINUX_CDROM return true;#else return false;#endif /* HAVE_LINUX_CDROM */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -