⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _cdio_linux.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    $Id: _cdio_linux.c,v 1.4 2006/09/26 22:18:44 dgp85 Exp $    Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>    Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>    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*//* This file contains Linux-specific code and implements low-level    control of the CD drive.*/#ifdef HAVE_CONFIG_H# include "config.h"#endifstatic const char _rcsid[] = "$Id: _cdio_linux.c,v 1.4 2006/09/26 22:18:44 dgp85 Exp $";#include <string.h>#include <cdio/sector.h>#include <cdio/util.h>#include <cdio/types.h>#include <cdio/scsi_mmc.h>#include <cdio/cdtext.h>#include "cdtext_private.h"#include "cdio_assert.h"#include "cdio_private.h"#ifdef HAVE_LINUX_CDROM#if defined(HAVE_LINUX_VERSION_H)# include <linux/version.h># if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)#   define __CDIO_LINUXCD_BUILD# else#  error "You need a kernel greater than 2.2.16 to have CDROM support"# endif#else #  error "You need <linux/version.h> to have CDROM support"#endif#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <mntent.h>#include <linux/cdrom.h>#include <scsi/scsi.h>#include <scsi/sg.h>#include <scsi/scsi_ioctl.h>#include <sys/mount.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>typedef enum {  _AM_NONE,  _AM_IOCTL,  _AM_READ_CD,  _AM_READ_10} access_mode_t;typedef struct {  /* Things common to all drivers like this.      This must be first. */  generic_img_private_t gen;   access_mode_t access_mode;  /* Some of the more OS specific things. */  /* Entry info for each track, add 1 for leadout. */  struct cdrom_tocentry  tocent[CDIO_CD_MAX_TRACKS+1];   struct cdrom_tochdr    tochdr;} _img_private_t;/* Some ioctl() errno values which occur when the tray is empty */#define ERRNO_TRAYEMPTY(errno)	\	((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))/**** prototypes for static functions ****/static bool is_cdrom_linux(const char *drive, char *mnttype);static bool read_toc_linux (void *p_user_data);static int  run_scsi_cmd_linux( const void *p_user_data, 				unsigned int i_timeout,				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 );static access_mode_t str_to_access_mode_linux(const char *psz_access_mode) {  const access_mode_t default_access_mode = _AM_IOCTL;  if (NULL==psz_access_mode) return default_access_mode;    if (!strcmp(psz_access_mode, "IOCTL"))    return _AM_IOCTL;  else if (!strcmp(psz_access_mode, "READ_CD"))    return _AM_READ_CD;  else if (!strcmp(psz_access_mode, "READ_10"))    return _AM_READ_10;  else {    cdio_warn ("unknown access type: %s. Default IOCTL used.", 	       psz_access_mode);    return default_access_mode;  }}static char *check_mounts_linux(const char *mtab){  FILE *mntfp;  struct mntent *mntent;    mntfp = setmntent(mtab, "r");  if ( mntfp != NULL ) {    char *tmp;    char *mnt_type;    char *mnt_dev;        while ( (mntent=getmntent(mntfp)) != NULL ) {      mnt_type = malloc(strlen(mntent->mnt_type) + 1);      if (mnt_type == NULL)	continue;  /* maybe you'll get lucky next time. */            mnt_dev = malloc(strlen(mntent->mnt_fsname) + 1);      if (mnt_dev == NULL) {	free(mnt_type);	continue;      }            strcpy(mnt_type, mntent->mnt_type);      strcpy(mnt_dev, mntent->mnt_fsname);            /* Handle "supermount" filesystem mounts */      if ( strcmp(mnt_type, "supermount") == 0 ) {	tmp = strstr(mntent->mnt_opts, "fs=");	if ( tmp ) {	  free(mnt_type);	  mnt_type = strdup(tmp + strlen("fs="));	  if ( mnt_type ) {	    tmp = strchr(mnt_type, ',');	    if ( tmp ) {	      *tmp = '\0';	    }	  }	}	tmp = strstr(mntent->mnt_opts, "dev=");	if ( tmp ) {	  free(mnt_dev);	  mnt_dev = strdup(tmp + strlen("dev="));	  if ( mnt_dev ) {	    tmp = strchr(mnt_dev, ',');	    if ( tmp ) {	      *tmp = '\0';	    }	  }	}      }      if ( strcmp(mnt_type, "iso9660") == 0 ) {	if (is_cdrom_linux(mnt_dev, mnt_type) > 0) {	  free(mnt_type);	  endmntent(mntfp);	  return mnt_dev;	}      }      free(mnt_dev);      free(mnt_type);    }    endmntent(mntfp);  }  return NULL;}/*!  Return the value associated with the key "arg".*/static const char *get_arg_linux (void *env, const char key[]){  _img_private_t *_obj = env;  if (!strcmp (key, "source")) {    return _obj->gen.source_name;  } else if (!strcmp (key, "access-mode")) {    switch (_obj->access_mode) {    case _AM_IOCTL:      return "ioctl";    case _AM_READ_CD:      return "READ_CD";    case _AM_READ_10:      return "READ_10";    case _AM_NONE:      return "no access method";    }  }   return NULL;}#undef USE_LINUX_CAP#ifdef USE_LINUX_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. */static voidget_drive_cap_linux (const void *p_user_data,		     /*out*/ cdio_drive_read_cap_t  *p_read_cap,		     /*out*/ cdio_drive_write_cap_t *p_write_cap,		     /*out*/ cdio_drive_misc_cap_t  *p_misc_cap){  const _img_private_t *p_env = p_user_data;  int32_t i_drivetype;  i_drivetype = ioctl (p_env->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT);  if (i_drivetype < 0) {    *p_read_cap  = CDIO_DRIVE_CAP_ERROR;    *p_write_cap = CDIO_DRIVE_CAP_ERROR;    *p_misc_cap  = CDIO_DRIVE_CAP_ERROR;    return;  }    *p_read_cap  = 0;  *p_write_cap = 0;  *p_misc_cap  = 0;  /* Reader */  if (i_drivetype & CDC_PLAY_AUDIO)     *p_read_cap  |= CDIO_DRIVE_CAP_READ_AUDIO;  if (i_drivetype & CDC_CD_R)     *p_read_cap  |= CDIO_DRIVE_CAP_READ_CD_R;  if (i_drivetype & CDC_CD_RW)     *p_read_cap  |= CDIO_DRIVE_CAP_READ_CD_RW;  if (i_drivetype & CDC_DVD)     *p_read_cap  |= CDIO_DRIVE_CAP_READ_DVD_ROM;  /* Writer */  if (i_drivetype & CDC_CD_RW)     *p_read_cap  |= CDIO_DRIVE_CAP_WRITE_CD_RW;  if (i_drivetype & CDC_DVD_R)     *p_read_cap  |= CDIO_DRIVE_CAP_WRITE_DVD_R;  if (i_drivetype & CDC_DVD_RAM)     *p_read_cap  |= CDIO_DRIVE_CAP_WRITE_DVD_RAM;  /* Misc */  if (i_drivetype & CDC_CLOSE_TRAY)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY;  if (i_drivetype & CDC_OPEN_TRAY)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_EJECT;  if (i_drivetype & CDC_LOCK)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_LOCK;  if (i_drivetype & CDC_SELECT_SPEED)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_SELECT_SPEED;  if (i_drivetype & CDC_SELECT_DISC)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_SELECT_DISC;  if (i_drivetype & CDC_MULTI_SESSION)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION;  if (i_drivetype & CDC_MEDIA_CHANGED)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED;  if (i_drivetype & CDC_RESET)     *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_RESET;}#endif/*!  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_linux (const void *p_user_data) {  struct cdrom_mcn mcn;  const _img_private_t *p_env = p_user_data;  memset(&mcn, 0, sizeof(mcn));  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_linux(void *p_user_data, track_t i_track) {  _img_private_t *p_env = p_user_data;    if ( !p_env ) return TRACK_FORMAT_ERROR;  if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;  if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)       || i_track < p_env->gen.i_first_track)    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 & CDIO_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 boolget_track_green_linux(void *p_user_data, track_t i_track) {  _img_private_t *p_env = p_user_data;    if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;  if (i_track >= (p_env->gen.i_tracks+p_env->gen.i_first_track)       || i_track < p_env->gen.i_first_track)    return false;  i_track -= p_env->gen.i_first_track;  /* FIXME: Dunno if this is the right way, but it's what      I was using in cd-info for a while.   */  return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);}/*!    Return the starting MSF (minutes/secs/frames) for track number  track_num in obj.  Track numbers usually start at something   greater than 0, usually 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 boolget_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf){  _img_private_t *p_env = p_user_data;  if (NULL == msf) return false;  if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;  if (i_track == CDIO_CDROM_LEADOUT_TRACK)     i_track = p_env->gen.i_tracks + p_env->gen.i_first_track;  if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)       || i_track < p_env->gen.i_first_track) {    return false;  } else {    struct cdrom_msf0  *msf0=       &p_env->tocent[i_track-p_env->gen.i_first_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;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -