📄 _cdio_bsdi.c
字号:
/*! Set the key "arg" to "value" in source device.*/static int_set_arg_bsdi (void *user_data, const char key[], const char value[]){ _img_private_t *p_env = 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")) { if (!strcmp(value, "IOCTL")) p_env->access_mode = _AM_IOCTL; else cdio_warn ("unknown access type: %s. ignored.", value); } else return -1; 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_bsdi (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-1].cdte_track = i; p_env->tocent[i-1].cdte_format = CDROM_MSF; if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-1]) == -1) { cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } /**** struct cdrom_msf0 *msf= &p_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= &p_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;}/*! Eject media in CD drive. If successful, as a side effect we also free obj. */static int _eject_media_bsdi (void *user_data) { _img_private_t *p_env = user_data; int ret=2; int status; int fd; close(p_env->gen.fd); p_env->gen.fd = -1; if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) { switch(status) { case CDS_TRAY_OPEN: if((ret = ioctl(fd, CDROMCLOSETRAY, 0)) != 0) { cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); } break; case CDS_DISC_OK: if((ret = ioctl(fd, CDROMEJECT, 0)) != 0) { cdio_warn("ioctl CDROMEJECT failed: %s\n", strerror(errno)); } break; } ret=0; } else { cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); ret=1; } close(fd); } return 2;}/*! Return the value associated with the key "arg".*/static const char *_get_arg_bsdi (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_IOCTL: return "ioctl"; case _AM_NONE: return "no access method"; } } return NULL;}/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */static char *_get_mcn_bsdi (const void *user_data) { struct cdrom_mcn mcn; const _img_private_t *p_env = user_data; if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0) return NULL; return strdup(mcn.medium_catalog_number);}/*! Get format of track. */static track_format_tget_track_format_bsdi(void *user_data, track_t i_track) { _img_private_t *p_env = user_data; if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; if (i_track > p_env->gen.i_tracks || i_track == 0) return TRACK_FORMAT_ERROR; i_track -= p_env->gen.i_first_track; /* This is pretty much copied from the "badly broken" cdrom_count_tracks in linux/cdrom.c. */ if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) { if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK) return TRACK_FORMAT_CDI; else if (p_env->tocent[i_track].cdte_format == CDIO_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 bool_get_track_green_bsdi(void *user_data, track_t i_track) { _img_private_t *p_env = user_data; if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; if (i_track > p_env->gen.i_tracks+1 || i_track == 0) return false; /* FIXME: Dunno if this is the right way, but it's what I was using in cdinfo for a while. */ return ((p_env->tocent[i_track-1].cdte_ctrl & 2) != 0);}/*! Return the starting MSF (minutes/secs/frames) for 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 bool_get_track_msf_bsdi(void *user_data, track_t i_track, msf_t *msf){ _img_private_t *p_env = user_data; if (NULL == msf) return false; if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; if (i_track > p_env->gen.i_tracks+1 || i_track == 0) { return false; } i_track -= p_env->gen.i_first_track; { struct cdrom_msf0 *msf0= &p_env->tocent[i_track].cdte_addr.msf; msf->m = cdio_to_bcd8(msf0->minute); msf->s = cdio_to_bcd8(msf0->second); msf->f = cdio_to_bcd8(msf0->frame); return true; }}#endif /* HAVE_BSDI_CDROM *//*! Return an array of strings giving possible CD devices. */char **cdio_get_devices_bsdi (void){#ifndef HAVE_BSDI_CDROM return NULL;#else char drive[40]; char **drives = NULL; unsigned int num_drives=0; bool exists=true; char c; /* Scan the system for CD-ROM drives. */#ifdef USE_ETC_FSTAB struct fstab *fs; setfsent(); /* Check what's in /etc/fstab... */ while ( (fs = getfsent()) ) { if (strncmp(fs->fs_spec, "/dev/sr", 7)) cdio_add_device_list(&drives, fs->fs_spec, &num_drives); } #endif /* Scan the system for CD-ROM drives. Not always 100% reliable, so use the USE_MNTENT code above first. */ for ( c='0'; exists && c <='9'; c++ ) { sprintf(drive, "/dev/rsr%cc", c); exists = cdio_is_cdrom(drive, NULL); if ( exists ) { cdio_add_device_list(&drives, drive, &num_drives); } } cdio_add_device_list(&drives, NULL, &num_drives); return drives;#endif /*HAVE_BSDI_CDROM*/}/*! Return a string containing the default CD device if none is specified. */char *cdio_get_default_device_bsdi(void){ return strdup(DEFAULT_CDIO_DEVICE);}/*! 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_bsdi (const char *psz_source_name, const char *psz_access_mode){ if (psz_access_mode != NULL) cdio_warn ("there is only one access mode for bsdi. Arg %s ignored", psz_access_mode); return cdio_open_bsdi(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_bsdi (const char *psz_orig_source){#ifdef HAVE_BSDI_CDROM CdIo *ret; _img_private_t *_data; char *psz_source; cdio_funcs _funcs = { .eject_media = _eject_media_bsdi, .free = cdio_generic_free, .get_arg = _get_arg_bsdi, .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_bsdi, .get_devices = cdio_get_devices_bsdi, .get_drive_cap = scsi_mmc_get_drive_cap_generic, .get_discmode = get_discmode_generic, .get_first_track_num= get_first_track_num_generic, .get_hwinfo = NULL, .get_mcn = _get_mcn_bsdi, .get_num_tracks = get_num_tracks_generic, .get_track_format = get_track_format_bsdi, .get_track_green = _get_track_green_bsdi, .get_track_lba = NULL, /* This could be implemented if need be. */ .get_track_msf = _get_track_msf_bsdi, .lseek = cdio_generic_lseek, .read = cdio_generic_read, .read_audio_sectors = _read_audio_sectors_bsdi, .read_mode1_sector = _read_mode1_sector_bsdi, .read_mode1_sectors = _read_mode1_sectors_bsdi, .read_mode2_sector = _read_mode2_sector_bsdi, .read_mode2_sectors = _read_mode2_sectors_bsdi, .read_toc = &read_toc_bsdi, .run_scsi_mmc_cmd = &run_scsi_cmd_bsdi, .set_arg = _set_arg_bsdi, .stat_size = _stat_size_bsdi }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_IOCTL; _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_linux(); if (NULL == psz_source) return NULL; _set_arg_bsdi(_data, "source", psz_source); free(psz_source); } else { if (cdio_is_device_generic(psz_orig_source)) _set_arg_bsdi(_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 return NULL; } } ret = cdio_new ( (void *) _data, &_funcs); if (ret == NULL) return NULL; if (_cdio_init(_data)) return ret; else { cdio_generic_free (_data); return NULL; } #else return NULL;#endif /* HAVE_BSDI_CDROM */}boolcdio_have_bsdi (void){#ifdef HAVE_BSDI_CDROM return true;#else return false;#endif /* HAVE_BSDI_CDROM */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -