Exemple #1
0
driver_return_code_t
audio_get_volume_win32ioctl (void *p_user_data, 
			     /*out*/ cdio_audio_volume_t *p_volume)
{
  const _img_private_t *p_env = p_user_data;
  DWORD dw_bytes_returned;

  bool b_success = 
    DeviceIoControl(p_env->h_device_handle, IOCTL_CDROM_GET_VOLUME,
		    NULL, 0, 
		    p_volume, (DWORD) sizeof(cdio_audio_volume_t), 
		    &dw_bytes_returned, NULL);

  if ( ! b_success ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
}
Exemple #2
0
/*!
  Read the Super block of an ISO 9660 image. This is the 
  Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume 
  Descriptor if (Joliet) extensions are acceptable.
*/
bool 
iso9660_fs_read_superblock (CdIo_t *p_cdio, 
			    iso_extension_mask_t iso_extension_mask)
{
  if (!p_cdio) return false;
  
  {
    generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
    iso9660_pvd_t         *p_pvd = &(p_env->pvd);
    iso9660_svd_t         *p_svd = &(p_env->svd);
    char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
    driver_return_code_t driver_return;

    if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) )
      return false;
    
    p_env->i_joliet_level = 0;
    
    driver_return = 
      cdio_read_data_sectors ( p_cdio, buf, ISO_PVD_SECTOR+1, ISO_BLOCKSIZE,
			       1 );

    if (DRIVER_OP_SUCCESS == driver_return) {
      /* The size of a PVD or SVD is smaller than a sector. So we
	 allocated a bigger block above (buf) and now we'll copy just
	 the part we need to save.
      */
      cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t));
      memcpy(p_svd, buf, sizeof(iso9660_svd_t));
  
      if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) {
	if (p_svd->escape_sequences[0] == 0x25 
	    && p_svd->escape_sequences[1] == 0x2f) {
	  switch (p_svd->escape_sequences[2]) {
	  case 0x40:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) 
	      p_env->i_joliet_level = 1;
	    break;
	  case 0x43:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) 
	      p_env->i_joliet_level = 2;
	    break;
	  case 0x45:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) 
	      p_env->i_joliet_level = 3;
	    break;
	  default:
	    cdio_info("Supplementary Volume Descriptor found, but not Joliet");
	  }
	  if (p_env->i_joliet_level > 0) {
	    cdio_info("Found Extension: Joliet Level %d", 
		      p_env->i_joliet_level);
	  }
	}
      }
    }
  }

  return true;
}
Exemple #3
0
/*!
   Reads an audio device using the DeviceIoControl method into data
   starting from lsn.  Returns 0 if no error.
 */
driver_return_code_t
read_audio_sectors_win32ioctl (_img_private_t *p_env, void *data, lsn_t lsn, 
			       unsigned int nblocks) 
{
  DWORD dw_bytes_returned;
  RAW_READ_INFO cdrom_raw;
  
  /* Initialize CDROM_RAW_READ structure */
  cdrom_raw.DiskOffset.QuadPart = (long long) CDIO_CD_FRAMESIZE_RAW * lsn;
  cdrom_raw.SectorCount = nblocks;
  cdrom_raw.TrackMode = CDDA;
  
  if( DeviceIoControl( p_env->h_device_handle,
		       IOCTL_CDROM_RAW_READ, &cdrom_raw,
		       sizeof(RAW_READ_INFO), data,
		       CDIO_CD_FRAMESIZE_RAW * nblocks,
		       &dw_bytes_returned, NULL ) == 0 ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) {
      cdio_info("Error reading audio-mode lsn %lu\n%s (%ld))", 
		(long unsigned int) lsn, psz_msg, i_err);
    } else {
      cdio_info("Error reading audio-mode lsn %lu\n (%ld))",
		(long unsigned int) lsn, i_err);
    }
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
}
Exemple #4
0
/*!
  Playing starting at given MSF through analog output
  
  @param p_cdio the CD object to be acted upon.
*/
driver_return_code_t
audio_play_msf_win32ioctl (void *p_user_data, msf_t *p_start_msf, 
			   msf_t *p_end_msf)
{
  const _img_private_t *p_env = p_user_data;
  CDROM_PLAY_AUDIO_MSF play;
  DWORD dw_bytes_returned;

  play.StartingM = cdio_from_bcd8(p_start_msf->m);
  play.StartingS = cdio_from_bcd8(p_start_msf->s);
  play.StartingF = cdio_from_bcd8(p_start_msf->f);

  play.EndingM   = cdio_from_bcd8(p_end_msf->m);
  play.EndingS   = cdio_from_bcd8(p_end_msf->s);
  play.EndingF   = cdio_from_bcd8(p_end_msf->f);

  bool b_success = 
    DeviceIoControl(p_env->h_device_handle, IOCTL_CDROM_PLAY_AUDIO_MSF,
		    &play, sizeof(play), NULL, 0, &dw_bytes_returned, NULL);
  
  if ( ! b_success ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
  
}
Exemple #5
0
/*!
  Read Audio Subchannel information
  
  @param p_cdio the CD object to be acted upon.
  
*/
driver_return_code_t
audio_read_subchannel_win32ioctl (void *p_user_data, 
				  cdio_subchannel_t *p_subchannel)
{
  const _img_private_t *p_env = p_user_data;
  DWORD dw_bytes_returned;
  CDROM_SUB_Q_DATA_FORMAT q_data_format;
  SUB_Q_CHANNEL_DATA q_subchannel_data;
  
  q_data_format.Format = CDIO_SUBCHANNEL_CURRENT_POSITION;
  q_data_format.Track=0; /* Not sure if this has to be set or if so what
			    it should be. */
  
  if( ! DeviceIoControl( p_env->h_device_handle,
		       IOCTL_CDROM_READ_Q_CHANNEL,
		       &q_data_format, sizeof(q_data_format), 
		       &q_subchannel_data, sizeof(q_subchannel_data),
		       &dw_bytes_returned, NULL ) ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  p_subchannel->audio_status = 
    q_subchannel_data.CurrentPosition.Header.AudioStatus;
  p_subchannel->track = 
    q_subchannel_data.CurrentPosition.TrackNumber;
  p_subchannel->index = 
    q_subchannel_data.CurrentPosition.IndexNumber;
  p_subchannel->index = 
    q_subchannel_data.CurrentPosition.IndexNumber;
  p_subchannel->address = q_subchannel_data.CurrentPosition.ADR;
  p_subchannel->control = q_subchannel_data.CurrentPosition.Control;

  { 
    const UCHAR *abs_addr = 
      q_subchannel_data.CurrentPosition.AbsoluteAddress;
    const UCHAR *rel_addr = 
      q_subchannel_data.CurrentPosition.TrackRelativeAddress;

    p_subchannel->abs_addr.m = cdio_to_bcd8(abs_addr[1]);
    p_subchannel->abs_addr.s = cdio_to_bcd8(abs_addr[2]);
    p_subchannel->abs_addr.f = cdio_to_bcd8(abs_addr[3]);
    p_subchannel->rel_addr.m = cdio_to_bcd8(rel_addr[1]);
    p_subchannel->rel_addr.s = cdio_to_bcd8(rel_addr[2]);
    p_subchannel->rel_addr.f = cdio_to_bcd8(rel_addr[3]);
  }

  return DRIVER_OP_SUCCESS;
}
Exemple #6
0
static bool
ucs2be_to_locale(ICONV_CONST char *psz_ucs2be,  size_t i_inlen, 
		 char **p_psz_out,  size_t i_outlen)
{

  iconv_t ic = 
#if defined(HAVE_LANGINFO_CODESET)
    iconv_open(nl_langinfo(CODESET), "UCS-2BE");
#else 
    iconv_open("ASCII", "UCS-2BE");
#endif

  int rc;
  char *psz_buf = NULL;
  char *psz_buf2;
  int i_outlen_max = i_outlen;
  int i_outlen_actual;

  if (-1 == (size_t) ic) {
#if defined(HAVE_LANGINFO_CODESET)
    cdio_info("Failed to get conversion table for locale, trying ASCII");
    ic = iconv_open("ASCII", "UCS-2BE");
    if (-1 == (size_t) ic) {
      cdio_info("Failed to get conversion table for ASCII too");
      return false;
    }
#else 
    cdio_info("Failed to get conversion table for locale");
    return false;
#endif
  }
  
  psz_buf = (char *) realloc(psz_buf, i_outlen);
  psz_buf2 = psz_buf;
  if (!psz_buf) {
    /* XXX: report out of memory error */
    goto error;
  }
  rc = iconv(ic, &psz_ucs2be, &i_inlen, &psz_buf2, &i_outlen);
  iconv_close(ic);
  if ((rc == -1) && (errno != E2BIG)) {
    /* conversion failed */
    goto error;
  }
  i_outlen_actual = i_outlen_max - i_outlen;
  *p_psz_out = malloc(i_outlen_actual + 1);
  memcpy(*p_psz_out, psz_buf, i_outlen_actual);
  *(*p_psz_out + i_outlen_actual) = '\0';
  free(psz_buf);
  return true;
 error:
  free(psz_buf);
  *p_psz_out = NULL; 
  return false;
}
Exemple #7
0
/*!
  Close the tray of a CD-ROM
  
  @param p_user_data the CD object to be acted upon.
  
*/
driver_return_code_t 
close_tray_win32ioctl (const char *psz_win32_drive)
{
#ifdef WIN32
  DWORD dw_bytes_returned;
  DWORD dw_access_flags;
  
  OSVERSIONINFO ov;
  HANDLE h_device_handle;
  bool b_success;
  
  memset(&ov,0,sizeof(OSVERSIONINFO));
  ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  GetVersionEx(&ov);
  
  if((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) &&        
     (ov.dwMajorVersion>4))
    dw_access_flags = GENERIC_READ|GENERIC_WRITE;  /* add gen write on W2k/XP */
  else dw_access_flags = GENERIC_READ;

  h_device_handle = CreateFile( psz_win32_drive, 
				dw_access_flags,
				FILE_SHARE_READ | FILE_SHARE_WRITE, 
				NULL, 
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL, 
				NULL );

  if( h_device_handle == INVALID_HANDLE_VALUE ) {
    return DRIVER_OP_ERROR;
  }

  b_success = 
    DeviceIoControl(h_device_handle, IOCTL_STORAGE_LOAD_MEDIA2,
		    NULL, (DWORD) 0, NULL, 0, &dw_bytes_returned, NULL);
  

  CloseHandle(h_device_handle);
  
  if ( ! b_success ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
#else 
  return DRIVER_OP_UNSUPPORTED;
#endif
}
Exemple #8
0
/*!
  Run a SCSI MMC command. 
 
  env	        private CD structure 
  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.

  Return 0 if command completed successfully.
 */
int
run_mmc_cmd_win32ioctl( void *p_user_data, 
			unsigned int i_timeout_ms,
			unsigned int i_cdb, const mmc_cdb_t * p_cdb,
			cdio_mmc_direction_t e_direction, 
			unsigned int i_buf, /*in/out*/ void *p_buf )
{
  const _img_private_t *p_env = p_user_data;
  SCSI_PASS_THROUGH_DIRECT sptd;
  bool b_success;
  DWORD dw_bytes_returned;
  
  sptd.Length  = sizeof(sptd);
  sptd.PathId  = 0;      /* SCSI card ID will be filled in automatically */
  sptd.TargetId= 0;      /* SCSI target ID will also be filled in */
  sptd.Lun=0;            /* SCSI lun ID will also be filled in */
  sptd.CdbLength         = i_cdb;
  sptd.SenseInfoLength   = 0; /* Don't return any sense data */
  sptd.DataIn            = SCSI_MMC_DATA_READ == e_direction ? 
    SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT; 
  sptd.DataTransferLength= i_buf; 
  sptd.TimeOutValue      = msecs2secs(i_timeout_ms);
  sptd.DataBuffer        = (void *) p_buf;
  sptd.SenseInfoOffset   = 0;

  memcpy(sptd.Cdb, p_cdb, i_cdb);

  /* Send the command to drive */
  b_success = DeviceIoControl(p_env->h_device_handle,
			      IOCTL_SCSI_PASS_THROUGH_DIRECT,               
			      (void *)&sptd, 
			      (DWORD)sizeof(SCSI_PASS_THROUGH_DIRECT),
			      NULL, 0,                        
			      &dw_bytes_returned,
			      NULL);

  if ( !b_success ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
}
Exemple #9
0
/*!
  Run a SCSI MMC command.

  p_user_data   internal CD structure.
  i_timeout_ms  time in milliseconds we will wait for the command
                to complete. If this value is -1, use the default
		time-out value.
  i_cdb	        Size of p_cdb
  p_cdb	        CDB bytes.
  e_direction	direction the transfer is to go.
  i_buf	        Size of buffer
  p_buf	        Buffer for data, both sending and receiving
 */
static driver_return_code_t
run_mmc_cmd_freebsd( void *p_user_data, unsigned int i_timeout_ms,
		     unsigned int i_cdb, const mmc_cdb_t *p_cdb,
		     cdio_mmc_direction_t e_direction,
		     unsigned int i_buf, /*in/out*/ void *p_buf )
{
  const _img_private_t *p_env = p_user_data;
  int ret;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      ret = run_mmc_cmd_freebsd_cam( p_user_data, i_timeout_ms, i_cdb, p_cdb,
                                     e_direction, i_buf, p_buf );
      if (ret != 0)
        return DRIVER_OP_ERROR;
      return 0;
    case _AM_IOCTL:
      return DRIVER_OP_UNSUPPORTED;
    case _AM_NONE:
      cdio_info ("access mode not set");
      return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_ERROR;
}
Exemple #10
0
/*!
  Read the Super block of an ISO 9660 image. This is the
  Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume
  Descriptor if (Joliet) extensions are acceptable.
*/
bool
iso9660_ifs_read_superblock (iso9660_t *p_iso,
			     iso_extension_mask_t iso_extension_mask)
{
  iso9660_svd_t p_svd;  /* Secondary volume descriptor. */
  int i;

  if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd)))
    return false;

  p_iso->u_joliet_level = 0;

  /* There may be multiple Secondary Volume Descriptors (eg. El Torito + Joliet) */
  for (i=1; (0 != iso9660_iso_seek_read (p_iso, &p_svd, ISO_PVD_SECTOR+i, 1)); i++) {
    if (ISO_VD_END == from_711(p_svd.type) ) /* Last SVD */
      break;
    if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd.type) ) {
      /* We're only interested in Joliet => make sure the SVD isn't overwritten */
      if (p_iso->u_joliet_level == 0)
        memcpy(&(p_iso->svd), &p_svd, sizeof(iso9660_svd_t));
      if (p_svd.escape_sequences[0] == 0x25
	  && p_svd.escape_sequences[1] == 0x2f) {
	switch (p_svd.escape_sequences[2]) {
	case 0x40:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1)
	    p_iso->u_joliet_level = 1;
	  break;
	case 0x43:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2)
	    p_iso->u_joliet_level = 2;
	  break;
	case 0x45:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3)
	    p_iso->u_joliet_level = 3;
	  break;
	default:
	  cdio_info("Supplementary Volume Descriptor found, but not Joliet");
	}
	if (p_iso->u_joliet_level > 0) {
	  cdio_info("Found Extension: Joliet Level %d", p_iso->u_joliet_level);
	}
      }
    }
  }

  return true;
}
Exemple #11
0
static bool
check_track_is_blocksize_multiple(const char *psz_fname, 
				  track_t i_track, long i_size, 
				  uint16_t i_blocksize)
{
  if (i_size % i_blocksize) {
    cdio_info ("image %s track %d size (%ld) not a multiple"
	       " of the blocksize (%ld)", psz_fname, i_track, i_size, 
	       (long int) i_blocksize);
    if (i_size % M2RAW_SECTOR_SIZE == 0)
      cdio_info ("this may be a 2336-type disc image");
    else if (i_size % CDIO_CD_FRAMESIZE_RAW == 0)
      cdio_info ("this may be a 2352-type disc image");
    return false;
  }
  return true;
}
Exemple #12
0
/*!
  Read the Super block of an ISO 9660 image. This is the 
  Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume 
  Descriptor if (Joliet) extensions are acceptable.
*/
bool 
iso9660_ifs_read_superblock (iso9660_t *p_iso, 
			     iso_extension_mask_t iso_extension_mask)
{
  iso9660_svd_t *p_svd;  /* Secondary volume descriptor. */
  
  if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd)))
    return false;

  p_svd = &(p_iso->svd);
  p_iso->i_joliet_level = 0;

  if (0 != iso9660_iso_seek_read (p_iso, p_svd, ISO_PVD_SECTOR+1, 1)) {
    if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) {
      if (p_svd->escape_sequences[0] == 0x25 
	  && p_svd->escape_sequences[1] == 0x2f) {
	switch (p_svd->escape_sequences[2]) {
	case 0x40:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) 
	    p_iso->i_joliet_level = 1;
	  break;
	case 0x43:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) 
	    p_iso->i_joliet_level = 2;
	  break;
	case 0x45:
	  if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) 
	    p_iso->i_joliet_level = 3;
	  break;
	default:
	  cdio_info("Supplementary Volume Descriptor found, but not Joliet");
	}
	if (p_iso->i_joliet_level > 0) {
	  cdio_info("Found Extension: Joliet Level %d", p_iso->i_joliet_level);
	}
      }
    }
  }
  
  return true;
}
Exemple #13
0
static void
get_drive_cap_freebsd (const void *p_user_data,
		       cdio_drive_read_cap_t  *p_read_cap,
		       cdio_drive_write_cap_t *p_write_cap,
		       cdio_drive_misc_cap_t  *p_misc_cap)
{
  const _img_private_t *p_env = p_user_data;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      get_drive_cap_mmc (p_user_data, p_read_cap, p_write_cap, p_misc_cap);
    case _AM_IOCTL:
      cdio_info ("get_drive_cap not supported in ioctl access mode");
      return;
    case _AM_NONE:
      cdio_info ("access mode not set");
      return;
  }
}
Exemple #14
0
/*!
  Stop playing an audio CD.
  
  @param p_user_data the CD object to be acted upon.
  
*/
driver_return_code_t 
audio_stop_win32ioctl (void *p_user_data)
{
  const _img_private_t *p_env = p_user_data;
  DWORD dw_bytes_returned;
  
  bool b_success = 
    DeviceIoControl(p_env->h_device_handle, IOCTL_CDROM_STOP_AUDIO,
		    NULL, (DWORD) 0, NULL, 0, &dw_bytes_returned, NULL);

  if ( ! b_success ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) 
      cdio_info("Error: %s", psz_msg);
    else 
      cdio_info("Error: %ld", i_err);
    LocalFree(psz_msg);
    return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_SUCCESS;
}
Exemple #15
0
/*!
  Return the media catalog number MCN.

  Note: string is malloc'd so caller should free() then returned
  string when done with it.

  FIXME: This is just a guess.

 */
static char *
get_mcn_freebsd (const void *p_user_data) {
  const _img_private_t *p_env = p_user_data;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      return mmc_get_mcn(p_env->gen.cdio);
    case _AM_IOCTL:
      return mmc_get_mcn(p_env->gen.cdio);
    case _AM_NONE:
      cdio_info ("access mode not set");
      return NULL;
  }
  return NULL;
}
Exemple #16
0
/*!
  Eject media. Return 1 if successful, 0 otherwise.
 */
static int
eject_media_freebsd (void *p_user_data)
{
  _img_private_t *p_env = p_user_data;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      return eject_media_freebsd_cam(p_env);
    case _AM_IOCTL:
      return eject_media_freebsd_ioctl(p_env);
    case _AM_NONE:
      cdio_info ("access mode not set");
      return 0;
  }
  return 0;
}
Exemple #17
0
/*!
   Reads a single mode2 sector from cd device into data starting
   from i_lsn. Returns 0 if no error.
 */
static driver_return_code_t
read_mode2_sector_freebsd (void *p_user_data, void *data, lsn_t i_lsn,
			   bool b_form2)
{
  _img_private_t *p_env = p_user_data;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
    return read_mode2_sector_freebsd_cam(p_env, data, i_lsn, b_form2);
    case _AM_IOCTL:
      return read_mode2_sector_freebsd_ioctl(p_env, data, i_lsn, b_form2);
    case _AM_NONE:
      cdio_info ("access mode not set");
      return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_ERROR;
}
Exemple #18
0
/*!
  Eject media.
 */
static driver_return_code_t
eject_media_win32 (void *p_user_data) 
{
  const _img_private_t *p_env = p_user_data;
  char psz_drive[4];
  unsigned int i_device = strlen(p_env->gen.source_name);
    
  strcpy( psz_drive, "X:" );
  if (6 == i_device) {
    psz_drive[0] = p_env->gen.source_name[4];
  } else if (2 == i_device) {
    psz_drive[0] = p_env->gen.source_name[0];
  } else {
    cdio_info ("Can't pick out drive letter from device %s", 
	       p_env->gen.source_name);
    return DRIVER_OP_ERROR;
  }
  
  return open_close_media_win32(psz_drive, MCI_SET_DOOR_OPEN);
}
Exemple #19
0
/*!
   Reads i_blocks of audio sectors from cd device into data starting from lsn.
   Returns 0 if no error.
 */
static driver_return_code_t
read_audio_sectors_freebsd (void *p_user_data, void *p_buf, lsn_t i_lsn,
			     unsigned int i_blocks)
{
  _img_private_t *p_env = p_user_data;
  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      return mmc_read_sectors( p_env->gen.cdio, p_buf, i_lsn,
                                  CDIO_MMC_READ_TYPE_CDDA, i_blocks);
    case _AM_IOCTL:
      return read_audio_sectors_freebsd_ioctl(p_user_data, p_buf, i_lsn,
					      i_blocks);
    case _AM_NONE:
      cdio_info ("access mode not set");
      return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_ERROR;
}
Exemple #20
0
/*!
   Return the size of the CD in logical block address (LBA) units.
  @return the lsn. On error return CDIO_INVALID_LSN.
 */
static lsn_t
get_disc_last_lsn_freebsd (void *p_obj)
{
  _img_private_t *p_env = p_obj;

  if (!p_env) return CDIO_INVALID_LSN;

  switch (p_env->access_mode) {
    case _AM_CAM:
    case _AM_MMC_RDWR:
    case _AM_MMC_RDWR_EXCL:
      return get_disc_last_lsn_mmc(p_env);
    case _AM_IOCTL:
      return get_disc_last_lsn_freebsd_ioctl(p_env);
    case _AM_NONE:
      cdio_info ("access mode not set");
      return DRIVER_OP_ERROR;
  }
  return DRIVER_OP_ERROR;
}
Exemple #21
0
/*! 
  Get
  @return length of name field; 0: not found, -1: to be ignored 
*/
int 
get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, 
			/*out*/ char * psz_name, 
			/*in/out*/ iso9660_stat_t *p_stat)
{
  int len;
  unsigned char *chr;
  int symlink_len = 0;
  CONTINUE_DECLS;
  int i_namelen = 0;
  int truncate=0;

  if (!p_stat || nope == p_stat->rr.b3_rock) return 0;
  *psz_name = 0;

  SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len);
  /*repeat:*/
  {
    iso_extension_record_t * rr;
    int sig;
    int rootflag;
    
    while (len > 1){ /* There may be one byte for padding somewhere */
      rr = (iso_extension_record_t *) chr;
      if (rr->len == 0) goto out; /* Something got screwed up here */
      sig = *chr+(*(chr+1) << 8);
      chr += rr->len; 
      len -= rr->len;

      switch(sig){
      case SIG('S','P'):
	CHECK_SP(goto out);
	break;
      case SIG('C','E'): 
	{
	  iso711_t i_fname = from_711(p_iso9660_dir->filename.len);
	  if ('\0' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
	    break;
	  if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
	    break;
	}
	CHECK_CE;
	break;
      case SIG('E','R'):
	p_stat->rr.b3_rock = yep;
	cdio_debug("ISO 9660 Extensions: ");
	{ 
	  int p;
	  for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]);
	}
	break;
      case SIG('N','M'):
	/* Alternate name */
	p_stat->rr.b3_rock = yep;
	if (truncate) break;
	if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) {
	  i_namelen = sizeof("..");
	  strncat(psz_name, "..", i_namelen);
	} else if (rr->u.NM.flags & ISO_ROCK_NM_CURRENT) {
	  i_namelen = sizeof(".");
	  strncat(psz_name, ".", i_namelen);
	  break;
	}

	if (rr->u.NM.flags & ~1) {
	  cdio_info("Unsupported NM flag settings (%d)",rr->u.NM.flags);
	  break;
	}
	if((strlen(psz_name) + rr->len - 5) >= 254) {
	  truncate = 1;
	  break;
	}
	strncat(psz_name, rr->u.NM.name, rr->len - 5);
	i_namelen += rr->len - 5;
	break;
      case SIG('P','X'):
	/* POSIX file attributes */
	p_stat->rr.st_mode   = from_733(rr->u.PX.st_mode);
	p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks);
	p_stat->rr.st_uid    = from_733(rr->u.PX.st_uid);
	p_stat->rr.st_gid    = from_733(rr->u.PX.st_gid);
	p_stat->rr.b3_rock    = yep;
	break;
      case SIG('S','L'):
	{
	  /* Symbolic link */
	  uint8_t slen;
	  iso_rock_sl_part_t * p_sl;
	  iso_rock_sl_part_t * p_oldsl;
	  slen = rr->len - 5;
	  p_sl = &rr->u.SL.link;
	  p_stat->rr.i_symlink = symlink_len;
	  while (slen > 1){
	    rootflag = 0;
	    switch(p_sl->flags &~1){
	    case 0:
	      realloc_symlink(p_stat, p_sl->len);
	      memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]),
		     p_sl->text, p_sl->len);
	      p_stat->rr.i_symlink += p_sl->len;
	      break;
	    case 4:
	      realloc_symlink(p_stat, 1);
	      p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
	      /* continue into next case. */
	    case 2:
	      realloc_symlink(p_stat, 1);
	      p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
	      break;
	    case 8:
	      rootflag = 1;
	      realloc_symlink(p_stat, 1);
	      p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/';
	      break;
	    default:
	      cdio_warn("Symlink component flag not implemented");
	    }
	    slen -= p_sl->len + 2;
	    p_oldsl = p_sl;
	    p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2);
	    
	    if (slen < 2) {
	      if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0)) 
		p_stat->rr.i_symlink += 1;
	      break;
	    }
	    
	    /*
	     * If this component record isn't continued, then append a '/'.
	     */
	    if (!rootflag && (p_oldsl->flags & 1) == 0) {
	      realloc_symlink(p_stat, 1);
	      p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/';
	    }
	  }
	}
	symlink_len = p_stat->rr.i_symlink;
	realloc_symlink(p_stat, 1);
	p_stat->rr.psz_symlink[symlink_len]='\0';
	break;
      case SIG('R','E'):
	free(buffer);
	return -1;
      case SIG('T','F'): 
	/* Time stamp(s) for a file */
	{
	  int cnt = 0;
	  add_time(ISO_ROCK_TF_CREATE,     create);
	  add_time(ISO_ROCK_TF_MODIFY,     modify);
	  add_time(ISO_ROCK_TF_ACCESS,     access);
	  add_time(ISO_ROCK_TF_ATTRIBUTES, attributes);
	  add_time(ISO_ROCK_TF_BACKUP,     backup);
	  add_time(ISO_ROCK_TF_EXPIRATION, expiration);
	  add_time(ISO_ROCK_TF_EFFECTIVE,  effective);
	  p_stat->rr.b3_rock = yep;
	  break;
	}
      default:
	break;
      }
    }
  }
  free(buffer);
  return i_namelen; /* If 0, this file did not have a NM field */
 out:
  free(buffer);
  return 0;
}
Exemple #22
0
/*!
   Reads a single mode2 sector from cd device into data starting
   from lsn. Returns 0 if no error. 
 */
static int
_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, 
			 bool mode2_form2)
{
  char buf[M2RAW_SECTOR_SIZE] = { 0, };
  struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
  msf_t _msf;

  _img_private_t *_obj = env;

  cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
  msf->cdmsf_min0 = from_bcd8(_msf.m);
  msf->cdmsf_sec0 = from_bcd8(_msf.s);
  msf->cdmsf_frame0 = from_bcd8(_msf.f);

 retry:
  switch (_obj->access_mode)
    {
    case _AM_NONE:
      cdio_error ("no way to read mode2");
      return 1;
      break;
      
    case _AM_IOCTL:
      if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1)
	{
	  perror ("ioctl()");
	  return 1;
	  /* exit (EXIT_FAILURE); */
	}
      break;
      
    case _AM_READ_CD:
    case _AM_READ_10:
      if (_read_packet_mode2_sectors (_obj->gen.fd, buf, lsn, 1, 
				      (_obj->access_mode == _AM_READ_10)))
	{
	  perror ("ioctl()");
	  if (_obj->access_mode == _AM_READ_CD)
	    {
	      cdio_info ("READ_CD failed; switching to READ_10 mode...");
	      _obj->access_mode = _AM_READ_10;
	      goto retry;
	    }
	  else
	    {
	      cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
	      _obj->access_mode = _AM_IOCTL;
	      goto retry;
	    }
	  return 1;
	}
      break;
    }

  if (mode2_form2)
    memcpy (data, buf, M2RAW_SECTOR_SIZE);
  else
    memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
  
  return 0;
}
Exemple #23
0
/*!
  Read the Super block of an ISO 9660 image. This is the 
  Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume 
  Descriptor if (Joliet) extensions are acceptable.
*/
bool 
iso9660_fs_read_superblock (CdIo_t *p_cdio, 
			    iso_extension_mask_t iso_extension_mask)
{
  if (!p_cdio) return false;
  
  {
    generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
    iso9660_pvd_t         *p_pvd = &(p_env->pvd);
    iso9660_svd_t         *p_svd = &(p_env->svd);
    char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
    bool                   b_mode2;
    int i_rc;

    /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/
    switch(cdio_get_track_format(p_cdio, 1)) {
    case TRACK_FORMAT_CDI:
    case TRACK_FORMAT_XA:
      b_mode2 = true;
      break;
    case TRACK_FORMAT_DATA:
      b_mode2 = false;
      break;
    case TRACK_FORMAT_AUDIO: 
    case TRACK_FORMAT_PSX: 
    case TRACK_FORMAT_ERROR: 
    default:
      return false;
    }
  
    if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) )
      return false;
    
    p_env->i_joliet_level = 0;
    
    i_rc = (b_mode2)
      ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false)
      : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false);

    if (0 == i_rc) {
      /* The size of a PVD or SVD is smaller than a sector. So we
	 allocated a bigger block above (buf) and now we'll copy just
	 the part we need to save.
      */
      cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t));
      memcpy(p_svd, buf, sizeof(iso9660_svd_t));
  
      if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) {
	if (p_svd->escape_sequences[0] == 0x25 
	    && p_svd->escape_sequences[1] == 0x2f) {
	  switch (p_svd->escape_sequences[2]) {
	  case 0x40:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) 
	      p_env->i_joliet_level = 1;
	    break;
	  case 0x43:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) 
	      p_env->i_joliet_level = 2;
	    break;
	  case 0x45:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) 
	      p_env->i_joliet_level = 3;
	    break;
	  default:
	    cdio_info("Supplementary Volume Descriptor found, but not Joliet");
	  }
	  if (p_env->i_joliet_level > 0) {
	    cdio_info("Found Extension: Joliet Level %d", 
		      p_env->i_joliet_level);
	  }
	}
      }
    }
  }

  return true;
}
Exemple #24
0
/*!
  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_freebsd (const char *psz_orig_source_name, 
		      const char *psz_access_mode)
{

#ifdef HAVE_FREEBSD_CDROM
  CdIo *ret;
  _img_private_t *_data;
  char *psz_source_name;
  
  if (!psz_access_mode) 
      psz_access_mode = get_access_mode(psz_orig_source_name);

  cdio_funcs_t _funcs = {
    .audio_get_volume       = audio_get_volume_freebsd,
    .audio_pause            = audio_pause_freebsd,
    .audio_play_msf         = audio_play_msf_freebsd,
    .audio_play_track_index = audio_play_track_index_freebsd,
    .audio_read_subchannel  = audio_read_subchannel_freebsd,
    .audio_resume           = audio_resume_freebsd,
    .audio_set_volume       = audio_set_volume_freebsd,
    .audio_stop             = audio_stop_freebsd,
    .eject_media            = eject_media_freebsd,
    .free                   = free_freebsd,
    .get_arg                = get_arg_freebsd,
    .get_blocksize          = get_blocksize_mmc,
    .get_cdtext             = get_cdtext_generic,
    .get_default_device     = cdio_get_default_device_freebsd,
    .get_devices            = cdio_get_devices_freebsd,
    .get_disc_last_lsn      = get_disc_last_lsn_freebsd,
    .get_discmode           = get_discmode_generic,
    .get_drive_cap          = get_drive_cap_freebsd,
    .get_first_track_num    = get_first_track_num_generic,
    .get_media_changed      = get_media_changed_freebsd,
    .get_mcn                = get_mcn_freebsd,
    .get_num_tracks         = get_num_tracks_generic,
    .get_track_channels     = get_track_channels_generic,
    .get_track_copy_permit  = get_track_copy_permit_generic,
    .get_track_format       = get_track_format_freebsd,
    .get_track_green        = get_track_green_freebsd,
    .get_track_lba          = get_track_lba_freebsd, 
    .get_track_preemphasis  = get_track_preemphasis_generic,
    .get_track_msf          = NULL,
    .lseek                  = cdio_generic_lseek,
    .read                   = cdio_generic_read,
    .read_audio_sectors     = read_audio_sectors_freebsd,
    .read_data_sectors      = read_data_sectors_mmc,
    .read_mode2_sector      = read_mode2_sector_freebsd,
    .read_mode2_sectors     = read_mode2_sectors_freebsd,
    .read_toc               = read_toc_freebsd,
    .run_mmc_cmd            = run_mmc_cmd_freebsd,
    .set_arg                = set_arg_freebsd,
    .set_blocksize          = set_blocksize_mmc,
    .set_speed              = set_speed_freebsd,
  };

  _data                     = calloc(1, sizeof (_img_private_t));
  _data->access_mode        = str_to_access_mode_freebsd(psz_access_mode);
  _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_name) {
    psz_source_name=cdio_get_default_device_freebsd();
    if (NULL == psz_source_name) return NULL;
    _data->device  = psz_source_name;
    set_arg_freebsd(_data, "source", psz_source_name);
  } else {
    if (cdio_is_device_generic(psz_orig_source_name)) {
      set_arg_freebsd(_data, "source", psz_orig_source_name);
      _data->device  = strdup(psz_orig_source_name);
    } 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_name);
#endif
      free(_data);
      return NULL;
    }
  }
    
  ret = cdio_new ((void *)_data, &_funcs);
  if (ret == NULL) return NULL;

  if (cdio_generic_init(_data, O_RDONLY))
    if ( _data->access_mode == _AM_IOCTL ) {
      return ret;
    } else {
      if (init_freebsd_cam(_data)) 
	return ret;
      else {
	cdio_generic_free (_data);
	return NULL;
      }
    }
  else {
    cdio_generic_free (_data);
    return NULL;
  }
  
#else 
  return NULL;
#endif /* HAVE_FREEBSD_CDROM */

}
Exemple #25
0
/*!
  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_win32 (const char *psz_orig_source, const char *psz_access_mode)
{

#ifdef HAVE_WIN32_CDROM
  CdIo *ret;
  _img_private_t *_data;
  char *psz_source;

  cdio_funcs_t _funcs;

  memset( &_funcs, 0, sizeof(_funcs) );

  _funcs.eject_media        = _cdio_eject_media;
  _funcs.free               = _free_win32;
  _funcs.get_arg            = _get_arg_win32;
  _funcs.get_cdtext         = get_cdtext_generic;
  _funcs.get_default_device = cdio_get_default_device_win32;
  _funcs.get_devices        = cdio_get_devices_win32;
  _funcs.get_disc_last_lsn     = get_disc_last_lsn_win32;
  _funcs.get_discmode       = get_discmode_win32;
  _funcs.get_drive_cap         = get_drive_cap_mmc;
  _funcs.get_first_track_num= get_first_track_num_generic;
  _funcs.get_hwinfo         = NULL;
  _funcs.get_mcn            = _cdio_get_mcn;
  _funcs.get_num_tracks     = get_num_tracks_generic;
  _funcs.get_track_channels    = get_track_channels_generic,
  _funcs.get_track_copy_permit = get_track_copy_permit_generic,
  _funcs.get_track_format   = _cdio_get_track_format;
  _funcs.get_track_green    = _cdio_get_track_green;
  _funcs.get_track_lba         = NULL; /* This could be done if need be. */
  _funcs.get_track_msf      = _cdio_get_track_msf;
  _funcs.get_track_preemphasis = get_track_preemphasis_generic,
  _funcs.lseek              = NULL;
  _funcs.read               = NULL;
  _funcs.read_audio_sectors = _cdio_read_audio_sectors;
  _funcs.read_mode1_sector  = _cdio_read_mode1_sector;
  _funcs.read_mode1_sectors = _cdio_read_mode1_sectors;
  _funcs.read_mode2_sector  = _cdio_read_mode2_sector;
  _funcs.read_mode2_sectors = _cdio_read_mode2_sectors;
  _funcs.read_toc           = &read_toc_win32;
  _funcs.run_scsi_mmc_cmd   = &run_scsi_cmd_win32;
  _funcs.set_arg            = set_arg_win32;
  _funcs.set_blocksize         = set_blocksize_mmc;
  _funcs.set_speed             = set_speed_mmc;

  _data                 = _cdio_malloc (sizeof (_img_private_t));
  _data->access_mode    = str_to_access_mode_win32(psz_access_mode);
  _data->gen.init       = false;
  _data->gen.fd         = -1;

  if (NULL == psz_orig_source) {
    psz_source=cdio_get_default_device_win32();
    if (NULL == psz_source) return NULL;
    set_arg_win32(_data, "source", psz_source);
    free(psz_source);
  } else {
    if (cdio_is_device_win32(psz_orig_source))
      set_arg_win32(_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
      free(_data);
      return NULL;
    }
  }

  ret = cdio_new ((void *)_data, &_funcs);
  if (ret == NULL) return NULL;

  if (_cdio_init_win32(_data))
    return ret;
  else {
    _free_win32 (_data);
    return NULL;
  }
  
#else 
  return NULL;
#endif /* HAVE_WIN32_CDROM */

}
Exemple #26
0
/*!
  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_freebsd (const char *psz_orig_source_name,
		      const char *psz_access_mode)
{

#ifdef HAVE_FREEBSD_CDROM
  CdIo *ret;
  _img_private_t *_data;
  char *psz_source_name;
  int open_access_mode;  /* Access mode passed to cdio_generic_init. */

  cdio_funcs_t _funcs = {
    .audio_get_volume       = audio_get_volume_freebsd,
    .audio_pause            = audio_pause_freebsd,
    .audio_play_msf         = audio_play_msf_freebsd,
    .audio_play_track_index = audio_play_track_index_freebsd,
    .audio_read_subchannel  = audio_read_subchannel_freebsd,
    .audio_resume           = audio_resume_freebsd,
    .audio_set_volume       = audio_set_volume_freebsd,
    .audio_stop             = audio_stop_freebsd,
    .eject_media            = eject_media_freebsd,
    .free                   = free_freebsd,
    .get_arg                = get_arg_freebsd,
    .get_blocksize          = get_blocksize_mmc,
    .get_cdtext             = get_cdtext_generic,
    .get_cdtext_raw         = read_cdtext_generic,
    .get_default_device     = cdio_get_default_device_freebsd,
    .get_devices            = cdio_get_devices_freebsd,
    .get_disc_last_lsn      = get_disc_last_lsn_freebsd,
    .get_discmode           = get_discmode_generic,
    .get_drive_cap          = get_drive_cap_freebsd,
    .get_first_track_num    = get_first_track_num_generic,
    .get_media_changed      = get_media_changed_freebsd,
    .get_mcn                = get_mcn_freebsd,
    .get_num_tracks         = get_num_tracks_generic,
    .get_track_channels     = get_track_channels_generic,
    .get_track_copy_permit  = get_track_copy_permit_generic,
    .get_track_format       = get_track_format_freebsd,
    .get_track_green        = get_track_green_freebsd,
    .get_track_lba          = get_track_lba_freebsd,
    .get_track_preemphasis  = get_track_preemphasis_generic,
    .get_track_msf          = NULL,
    .get_track_isrc         = get_track_isrc_freebsd,
    .lseek                  = cdio_generic_lseek,
    .read                   = cdio_generic_read,
    .read_audio_sectors     = read_audio_sectors_freebsd,
    .read_data_sectors      = read_data_sectors_mmc,
    .read_mode2_sector      = read_mode2_sector_freebsd,
    .read_mode2_sectors     = read_mode2_sectors_freebsd,
    .read_toc               = read_toc_freebsd,
    .run_mmc_cmd            = run_mmc_cmd_freebsd,
    .set_arg                = set_arg_freebsd,
    .set_blocksize          = set_blocksize_mmc,
    .set_speed              = set_speed_freebsd,
  };

  if (!psz_access_mode)
      psz_access_mode = get_access_mode(psz_orig_source_name);

  _data                     = calloc(1, sizeof (_img_private_t));
  _data->access_mode        = str_to_access_mode_freebsd(psz_access_mode);
  _data->gen.init           = false;
  _data->gen.fd             = -1;
  _data->gen.toc_init       = false;
  _data->gen.b_cdtext_error = false;

  if (NULL == psz_orig_source_name) {
    psz_source_name=cdio_get_default_device_freebsd();
    if (NULL == psz_source_name) {
      cdio_generic_free (_data);
      return NULL;
    }
    _data->device  = psz_source_name;
    set_arg_freebsd(_data, "source", psz_source_name);
  } else {
    if (cdio_is_device_generic(psz_orig_source_name)) {
      set_arg_freebsd(_data, "source", psz_orig_source_name);
      _data->device  = strdup(psz_orig_source_name);
    } 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_name);
#endif
      cdio_generic_free (_data);
      return NULL;
    }
  }

  ret = cdio_new ((void *)_data, &_funcs);
  if (ret == NULL) {
    cdio_generic_free (_data);
    return NULL;
  }

  open_access_mode = 0;
  if (_AM_MMC_RDWR == _data->access_mode) {
    open_access_mode |= O_RDWR;
  } else if (_AM_MMC_RDWR_EXCL == _data->access_mode) {
    open_access_mode |= O_RDWR;
  } else {
    open_access_mode |= O_RDONLY;
  }
/*
  fprintf(stderr,
      "libcdio_DEBUG: am = %d (MMC_RDWR_EXCL = %d), open = %d (O_RDWR = %d)\n",
      _data->access_mode, _AM_MMC_RDWR_EXCL, open_access_mode, O_RDWR);
*/

  if (cdio_generic_init(_data, open_access_mode)) {
    if (_AM_MMC_RDWR_EXCL == _data->access_mode) {
      int os_errno, pass_dev_no = -1, flock_fd = -1, lock_result;
      char msg[4096];

      lock_result = freebsd_dev_lock(_data->gen.fd, _data->gen.source_name,
                                   &os_errno, &pass_dev_no, &flock_fd, msg, 0);
      if (lock_result <= 0) {
        cdio_warn ("%s", msg);
	goto err_exit;
      }
      /* One should rather keep this fd open until _data->gen.fd gets closed.
         It eventually locks a device sibling of _data->gen.source_name.
      */
      if (flock_fd > 0)
        close(flock_fd);
    }

    if ( _data->access_mode == _AM_IOCTL ) {
      return ret;
    } else {
      if (init_freebsd_cam(_data))
	return ret;
      }
    }

 err_exit:
    free(ret);
    cdio_generic_free(_data);
    return NULL;

#else
  return NULL;
#endif /* HAVE_FREEBSD_CDROM */
}
Exemple #27
0
/* 
   Disk and track information for a Nero file are located at the end
   of the file. This routine extracts that information.

   FIXME: right now psz_nrg_name is not used. It will be in the future.
 */
static bool
parse_nrg (_img_private_t *p_env, const char *psz_nrg_name, 
	   const cdio_log_level_t log_level)
{
  off_t footer_start;
  off_t size;
  char *footer_buf = NULL;
  if (!p_env) return false;
  size = cdio_stream_stat (p_env->gen.data_source);
  if (-1 == size) return false;

  {
    _footer_t buf;
    cdio_assert (sizeof (buf) == 12);
 
    cdio_stream_seek (p_env->gen.data_source, size - sizeof (buf), SEEK_SET);
    cdio_stream_read (p_env->gen.data_source, (void *) &buf, sizeof (buf), 1);
    
    if (buf.v50.ID == UINT32_TO_BE (NERO_ID)) {
      cdio_debug ("detected Nero version 5.0 (32-bit offsets) NRG magic");
      footer_start = uint32_to_be (buf.v50.footer_ofs); 
    } else if (buf.v55.ID == UINT32_TO_BE (NER5_ID)) {
      cdio_debug ("detected Nero version 5.5.x (64-bit offsets) NRG magic");
      footer_start = uint64_from_be (buf.v55.footer_ofs);
    } else {
      cdio_log (log_level, "Image not recognized as either version 5.0 or "
		"version 5.5.x-6.x type NRG");
      return false;
    }

    cdio_debug (".NRG footer start = %ld, length = %ld", 
	       (long) footer_start, (long) (size - footer_start));

    cdio_assert ((size - footer_start) <= 4096);

    footer_buf = calloc(1, (size_t)(size - footer_start));

    cdio_stream_seek (p_env->gen.data_source, footer_start, SEEK_SET);
    cdio_stream_read (p_env->gen.data_source, footer_buf, 
		      (size_t)(size - footer_start), 1);
  }
  {
    int pos = 0;

    while (pos < size - footer_start) {
      _chunk_t *chunk = (void *) (footer_buf + pos);
      uint32_t opcode = UINT32_FROM_BE (chunk->id);
      
      bool break_out = false;
      
      switch (opcode) {

      case CUES_ID: /* "CUES" Seems to have sector size 2336 and 150 sector
		       pregap seems to be included at beginning of image.
		       */
      case CUEX_ID: /* "CUEX" */ 
	{
	  unsigned entries = UINT32_FROM_BE (chunk->len);
	  _cuex_array_t *_entries = (void *) chunk->data;
	  
	  cdio_assert (p_env->mapping == NULL);
	  
	  cdio_assert ( sizeof (_cuex_array_t) == 8 );
	  cdio_assert ( UINT32_FROM_BE (chunk->len) % sizeof(_cuex_array_t) 
			== 0 );
	  
	  entries /= sizeof (_cuex_array_t);
	  
	  if (CUES_ID == opcode) {
	    lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn);
	    unsigned int idx;
	    unsigned int i = 0;
	    
	    cdio_debug ("CUES type image detected" );

	    /* CUES LSN has 150 pregap include at beginning? -/
	       cdio_assert (lsn == 0?);
	    */
	    
	    p_env->is_cues           = true; /* HACK alert. */
	    p_env->gen.i_tracks      = 0;
	    p_env->gen.i_first_track = 1;
	    for (idx = 1; idx < entries-1; idx += 2, i++) {
	      lsn_t sec_count;
	      int cdte_format = _entries[idx].addr_ctrl / 16;
	      int cdte_ctrl   = _entries[idx].type >> 4;

	      if ( COPY_PERMITTED & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= COPY_PERMITTED;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~COPY_PERMITTED;
	      }
	      
	      if ( PRE_EMPHASIS & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= PRE_EMPHASIS;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~PRE_EMPHASIS;
	      }
	      
	      if ( FOUR_CHANNEL_AUDIO & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= FOUR_CHANNEL_AUDIO;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~FOUR_CHANNEL_AUDIO;
	      }
	      
	      cdio_assert (_entries[idx].track == _entries[idx + 1].track);
	      
	      /* lsn and sec_count*2 aren't correct, but it comes closer on the
		 single example I have: svcdgs.nrg
		 We are picking up the wrong fields and/or not interpreting
		 them correctly.
	      */

	      switch (cdte_format) {
	      case 0:
		lsn = UINT32_FROM_BE (_entries[idx].lsn);
		break;
	      case 1: 
		{
#if 0
		  msf_t msf = (msf_t) _entries[idx].lsn;
		  lsn = cdio_msf_to_lsn(&msf);
#else
		  lsn = CDIO_INVALID_LSN;
#endif		  
		  cdio_log (log_level, 
			    "untested (i.e. probably wrong) CUE MSF code");
		  break;
		}
	      default:
		lsn = CDIO_INVALID_LSN;
		cdio_log(log_level,
			 "unknown cdte_format %d", cdte_format);
	      }
	      
	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);
	      
	      _register_mapping (p_env, lsn, sec_count*2, 
				 (lsn+CDIO_PREGAP_SECTORS) * M2RAW_SECTOR_SIZE,
				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true);
	    }
	  } else {
	    lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn);
	    unsigned int idx;
	    unsigned int i = 0;
	    
	    cdio_debug ("CUEX type image detected");

	    /* LSN must start at -150 (LBA 0)? */
	    cdio_assert (lsn == -150); 
	    
	    for (idx = 2; idx < entries; idx += 2, i++) {
	      lsn_t sec_count;
	      int cdte_format = _entries[idx].addr_ctrl >> 4;
	      int cdte_ctrl   = _entries[idx].type >> 4;

	      if ( COPY_PERMITTED & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= COPY_PERMITTED;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~COPY_PERMITTED;
	      }
	      
	      if ( PRE_EMPHASIS & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= PRE_EMPHASIS;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~PRE_EMPHASIS;
	      }
	      
	      if ( FOUR_CHANNEL_AUDIO & cdte_ctrl ) {
		if (p_env) p_env->tocent[i].flags |= FOUR_CHANNEL_AUDIO;
	      } else {
		if (p_env) p_env->tocent[i].flags &= ~FOUR_CHANNEL_AUDIO;
	      }
	      
	      /* extractnrg.pl has cdte_format for LBA's 0, and
		 for MSF 1. ???

		 FIXME: Should decode as appropriate for cdte_format.
	       */
	      cdio_assert ( cdte_format == 0 || cdte_format == 1 );

	      cdio_assert (_entries[idx].track != _entries[idx + 1].track);
	      
	      lsn       = UINT32_FROM_BE (_entries[idx].lsn);
	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);
	      
	      _register_mapping (p_env, lsn, sec_count - lsn, 
				 (lsn + CDIO_PREGAP_SECTORS)*M2RAW_SECTOR_SIZE,
				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true);
	    }
	  }
	  break;
	}
	
      case DAOX_ID: /* "DAOX" */ 
      case DAOI_ID: /* "DAOI" */
	{
	  _daox_t *_xentries = NULL;
	  _daoi_t *_ientries = NULL;
	  _dao_array_common_t *_dao_array_common = NULL;
	  _dao_common_t *_dao_common = (void *) chunk->data;
	  int disc_mode = _dao_common->unknown[1];
	  track_format_t track_format;
	  int i;

	  /* We include an extra 0 byte so these can be used as C strings.*/
	  p_env->psz_mcn = calloc(1, CDIO_MCN_SIZE+1);
	  memcpy(p_env->psz_mcn, &(_dao_common->psz_mcn), CDIO_MCN_SIZE);
	  p_env->psz_mcn[CDIO_MCN_SIZE] = '\0';

	  if (DAOX_ID == opcode) {
	    _xentries = (void *) chunk->data;
	    p_env->dtyp = _xentries->track_info[0].common.unknown[2];
	  } else {
	    _ientries = (void *) chunk->data;
	    p_env->dtyp = _ientries->track_info[0].common.unknown[2];
	  }

	  p_env->is_dao = true;
	  cdio_debug ("DAO%c tag detected, track format %d, mode %x\n", 
		      opcode==DAOX_ID ? 'X': 'I', p_env->dtyp, disc_mode);
	  switch (p_env->dtyp) {
	  case 0:
	    /* Mode 1 */
	    track_format     = TRACK_FORMAT_DATA;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_DATA;
	    break;
	  case 2:
	    /* Mode 2 form 1 */
	    disc_mode             = 0;
	    track_format     = TRACK_FORMAT_XA;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA;
	    break;
	  case 3:
	    /* Mode 2 */
	    track_format     = TRACK_FORMAT_XA;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */
	    break;
	  case 0x6:
	    /* Mode2 form mix */
	    track_format     = TRACK_FORMAT_XA;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_MIXED;
	    break;
	  case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */
	    track_format     = TRACK_FORMAT_XA;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */
	    break;
	  case 0x7:
	    track_format     = TRACK_FORMAT_AUDIO;
	    p_env->disc_mode = CDIO_DISC_MODE_CD_DA;
	    break;
	  default:
	    cdio_log (log_level, "Unknown track format %x\n", 
		      p_env->dtyp);
	    track_format = TRACK_FORMAT_AUDIO;
	  }
	  if (0 == disc_mode) {
	    for (i=0; i<p_env->gen.i_tracks; i++) {
	      p_env->tocent[i].track_format= track_format;
	      p_env->tocent[i].datastart   = 0;
	      p_env->tocent[i].track_green = false;
	      if (TRACK_FORMAT_AUDIO == track_format) {
		p_env->tocent[i].blocksize   = CDIO_CD_FRAMESIZE_RAW;
		p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE_RAW;
		p_env->tocent[i].endsize     = 0;
	      } else {
		p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE;
		p_env->tocent[i].datastart  =  0;
	      }
	    }
	  } else if (2 == disc_mode) {
	    for (i=0; i<p_env->gen.i_tracks; i++) {
	      p_env->tocent[i].track_green = true;
	      p_env->tocent[i].track_format= track_format;
	      p_env->tocent[i].datasize    = CDIO_CD_FRAMESIZE;
	      if (TRACK_FORMAT_XA == track_format) {
		p_env->tocent[i].datastart   = CDIO_CD_SYNC_SIZE 
		  + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
		p_env->tocent[i].endsize     = CDIO_CD_SYNC_SIZE 
		  + CDIO_CD_ECC_SIZE;
	      } else {
		p_env->tocent[i].datastart   = CDIO_CD_SYNC_SIZE 
		  + CDIO_CD_HEADER_SIZE;
		p_env->tocent[i].endsize     = CDIO_CD_EDC_SIZE 
		  + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE;
	      
	      }
	    }
	  } else if (0x20 == disc_mode) {
	    cdio_debug ("Mixed mode CD?\n");
	  } else {
	    /* Mixed mode CD */
	    cdio_log (log_level, 
		      "Don't know if mode 1, mode 2 or mixed: %x\n", 
		      disc_mode);
	  }

	  for (i=0; i<p_env->gen.i_tracks; i++) {

	    if (DAOX_ID == opcode) {
	      _dao_array_common = &_xentries->track_info[i].common;
	    } else {
	      _dao_array_common = &_ientries->track_info[i].common;
	    }
	    p_env->tocent[i].isrc = calloc(1, CDIO_ISRC_SIZE+1);
	    memcpy(p_env->tocent[i].isrc, _dao_array_common->psz_isrc, CDIO_ISRC_SIZE);
	    p_env->tocent[i].isrc[CDIO_ISRC_SIZE] = '\0';
	    if (p_env->tocent[i].isrc[0]) {
	       cdio_info("nrg isrc has value \"%s\"", p_env->tocent[i].isrc);
	    }

	    if (!p_env->tocent[i].datasize) {
	      continue;
	    }
	    if (DAOX_ID == opcode) {
	       p_env->tocent[i].pregap = (uint64_from_be
		(_xentries->track_info[i].index0)) / (p_env->tocent[i].datasize);
	    } else {
	       p_env->tocent[i].pregap = (uint32_from_be
		(_ientries->track_info[i].index0)) / (p_env->tocent[i].datasize);
	    }
	  }

	  break;
	}
      case NERO_ID: 
      case NER5_ID: 
	cdio_error ("unexpected nrg magic ID NER%c detected",
		    opcode==NERO_ID ? 'O': '5');
	free(footer_buf);
	return false;

      case END1_ID: /* "END!" */
	cdio_debug ("nrg end tag detected");
	break_out = true;
	break;
	
      case ETNF_ID: /* "ETNF" */ {
	unsigned entries = UINT32_FROM_BE (chunk->len);
	_etnf_array_t *_entries = (void *) chunk->data;
	
	cdio_assert (p_env->mapping == NULL);
	
	cdio_assert ( sizeof (_etnf_array_t) == 20 );
	cdio_assert ( UINT32_FROM_BE(chunk->len) % sizeof(_etnf_array_t) 
		      == 0 );
	
	entries /= sizeof (_etnf_array_t);
	
	cdio_debug ("SAO type image (ETNF) detected");
	
	{
	  int idx;
	  for (idx = 0; idx < entries; idx++) {
	    uint32_t _len = UINT32_FROM_BE (_entries[idx].length);
	    uint32_t _start = UINT32_FROM_BE (_entries[idx].start_lsn);
	    uint32_t _start2 = UINT32_FROM_BE (_entries[idx].start);
	    uint32_t track_mode= uint32_from_be (_entries[idx].type);
	    bool     track_green = true;
	    track_format_t track_format = TRACK_FORMAT_XA;
	    uint16_t  blocksize;     
	    
	    switch (track_mode) {
	    case 0:
	      /* Mode 1 */
	      track_format   = TRACK_FORMAT_DATA;
	      track_green    = false; /* ?? */
	      blocksize      = CDIO_CD_FRAMESIZE;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_DATA;
	      cdio_debug ("Format DATA, blocksize %u", CDIO_CD_FRAMESIZE);
	      break;
	    case 2:
	      /* Mode 2 form 1 */
	      track_format   = TRACK_FORMAT_XA;
	      track_green    = false; /* ?? */
	      blocksize      = CDIO_CD_FRAMESIZE;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA;
	      cdio_debug ("Format XA, blocksize %u", CDIO_CD_FRAMESIZE);
	      break;
	    case 3:
	      /* Mode 2 */
	      track_format   = TRACK_FORMAT_XA;
	      track_green    = true;
	      blocksize      = M2RAW_SECTOR_SIZE;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */
	      cdio_debug ("Format XA, blocksize %u", M2RAW_SECTOR_SIZE);
	      break;
	    case 06:
	      /* Mode2 form mix */
	      track_format   = TRACK_FORMAT_XA;
	      track_green    = true;
	      blocksize      = M2RAW_SECTOR_SIZE;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_MIXED;
	      cdio_debug ("Format MIXED CD, blocksize %u", M2RAW_SECTOR_SIZE);
	      break;
	    case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */
	      track_format   = TRACK_FORMAT_XA;
	      track_green    = true;
	      blocksize      = M2RAW_SECTOR_SIZE;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */
	      cdio_debug ("Format MIXED CD, blocksize %u", M2RAW_SECTOR_SIZE);
	      break;
	    case 7:
	      track_format   = TRACK_FORMAT_AUDIO;
	      track_green    = false;
	      blocksize      = CDIO_CD_FRAMESIZE_RAW;
	      p_env->disc_mode = CDIO_DISC_MODE_CD_DA;
	      cdio_debug ("Format CD_DA, blocksize %u", CDIO_CD_FRAMESIZE_RAW);
	      break;
	    default:
	      cdio_log (log_level, 
			"Don't know how to handle track mode (%lu)?",
			(long unsigned int) track_mode);
	      free(footer_buf);
	      return false;
	    }
	    
	    cdio_assert (_len % blocksize == 0);
	    
	    _len /= blocksize;
	    
	    cdio_assert (_start * blocksize == _start2);
	    
	    _start += idx * CDIO_PREGAP_SECTORS;
	    _register_mapping (p_env, _start, _len, _start2, blocksize,
			       track_format, track_green);

	  }
	}
	break;
      }
      
      case ETN2_ID: { /* "ETN2", same as above, but with 64bit stuff instead */
	unsigned entries = uint32_from_be (chunk->len);
	_etn2_array_t *_entries = (void *) chunk->data;
	
	cdio_assert (p_env->mapping == NULL);
	
	cdio_assert (sizeof (_etn2_array_t) == 32);
	cdio_assert (uint32_from_be (chunk->len) % sizeof (_etn2_array_t) == 0);
	
	entries /= sizeof (_etn2_array_t);
	
	cdio_debug ("SAO type image (ETN2) detected");

	{
	  int idx;
	  for (idx = 0; idx < entries; idx++) {
	    uint32_t _len = uint64_from_be (_entries[idx].length);
	    uint32_t _start = uint32_from_be (_entries[idx].start_lsn);
	    uint32_t _start2 = uint64_from_be (_entries[idx].start);
	    uint32_t track_mode= uint32_from_be (_entries[idx].type);
	    bool     track_green = true;
	    track_format_t track_format = TRACK_FORMAT_XA;
	    uint16_t  blocksize;     


	    switch (track_mode) {
	    case 0:
	      track_format = TRACK_FORMAT_DATA;
	      track_green  = false; /* ?? */
	      blocksize    = CDIO_CD_FRAMESIZE;
	      break;
	    case 2:
	      track_format = TRACK_FORMAT_XA;
	      track_green  = false; /* ?? */
	      blocksize    = CDIO_CD_FRAMESIZE;
	      break;
	    case 3:
	      track_format = TRACK_FORMAT_XA;
	      track_green  = true;
	      blocksize    = M2RAW_SECTOR_SIZE;
	      break;
	    case 7:
	      track_format = TRACK_FORMAT_AUDIO;
	      track_green  = false;
	      blocksize    = CDIO_CD_FRAMESIZE_RAW;
	      break;
	    default:
	      cdio_log (log_level, 
			"Don't know how to handle track mode (%lu)?",
			(long unsigned int) track_mode);
	      free(footer_buf);
	      return false;
	    }
	    
	    if (_len % blocksize != 0) {
	      cdio_log (log_level, 
			"length is not a multiple of blocksize " 
			 "len %lu, size %d, rem %lu", 
			 (long unsigned int) _len, blocksize, 
			 (long unsigned int) _len % blocksize);
	      if (0 == _len % CDIO_CD_FRAMESIZE) {
		cdio_log(log_level, "Adjusting blocksize to %d", 
			 CDIO_CD_FRAMESIZE);
		blocksize = CDIO_CD_FRAMESIZE;
	      } else if (0 == _len % M2RAW_SECTOR_SIZE) {
		cdio_log(log_level,
			 "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE);
		blocksize = M2RAW_SECTOR_SIZE;
	      } else if (0 == _len % CDIO_CD_FRAMESIZE_RAW) {
		cdio_log(log_level, 
			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW);
		blocksize = CDIO_CD_FRAMESIZE_RAW;
	      }
	    }
	    
	    _len /= blocksize;
	    
	    if (_start * blocksize != _start2) {
	      cdio_log (log_level,
			"%lu * %d != %lu", 
			 (long unsigned int) _start, blocksize, 
			 (long unsigned int) _start2);
	      if (_start * CDIO_CD_FRAMESIZE == _start2) {
		cdio_log(log_level,
			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE);
		blocksize = CDIO_CD_FRAMESIZE;
	      } else if (_start * M2RAW_SECTOR_SIZE == _start2) {
		cdio_log(log_level,
			 "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE);
		blocksize = M2RAW_SECTOR_SIZE;
	      } else if (_start * CDIO_CD_FRAMESIZE_RAW == _start2) {
		cdio_log(log_level,
			 "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW);
		blocksize = CDIO_CD_FRAMESIZE_RAW;
	      }
	    }
	    
	    _start += idx * CDIO_PREGAP_SECTORS;
	    _register_mapping (p_env, _start, _len, _start2, blocksize,
			       track_format, track_green);
	  }
	}
	break;
      }
	
      case SINF_ID: { /* "SINF" */
	
	uint32_t _sessions;
	
	cdio_assert (UINT32_FROM_BE (chunk->len) == 4);
	
	memcpy(&_sessions, chunk->data, 4);

	cdio_debug ("SINF: %lu sessions", 
		    (long unsigned int) UINT32_FROM_BE (_sessions));
      }
	break;
	
      case MTYP_ID: { /* "MTYP" */
	uint32_t mtyp_be;
	uint32_t mtyp;
	
	cdio_assert (UINT32_FROM_BE (chunk->len) == 4);

	memcpy(&mtyp_be, chunk->data, 4);
	mtyp = UINT32_FROM_BE (mtyp_be);

	cdio_debug ("MTYP: %lu", 
		    (long unsigned int) mtyp);

	if (mtyp != MTYP_AUDIO_CD) {
	  cdio_log (log_level,
		    "Unknown MTYP value: %u", (unsigned int) mtyp);
	}
	p_env->mtyp = mtyp;
      }
	break;
	
      case CDTX_ID: { /* "CD TEXT" */
        uint8_t *wdata = (uint8_t *) chunk->data;
        int len = UINT32_FROM_BE (chunk->len);
        cdio_assert (len % CDTEXT_LEN_PACK == 0);
        p_env->gen.cdtext = cdtext_init ();
        if(0 !=cdtext_data_init (p_env->gen.cdtext, wdata, len))
        {
          cdtext_destroy(p_env->gen.cdtext);
          free(p_env->gen.cdtext);
          p_env->gen.cdtext = NULL;
        }

        break;
      }

      default:
	cdio_log (log_level,
		  "unknown tag %8.8x seen", 
		  (unsigned int) UINT32_FROM_BE (chunk->id));
	break;
      }
	
      if (break_out)
	break;
      
      pos += 8;
      pos += UINT32_FROM_BE (chunk->len);
    }
Exemple #28
0
static void cued_parse_qsc(qsc_buffer_t *qsc, rip_context_t *rip)
{
    int flags;
    qsc_index_t index;
    lsn_t *currLsn;
    char *isrc;

    if (qsc_check_crc(qsc)) {
        ++rip->crcFailure;
        return;
    }

    ++rip->crcSuccess;

    switch (qsc_get_mode(qsc)) {

        case QSC_MODE_INDEX:
            if (!qsc_get_index(qsc, &index)) {

                // set this for ISRC case
                rip->trackHint = index.track;

                currLsn = &rip->ripData[index.track].indices[index.index];
                if (*currLsn == CDIO_INVALID_LSN || index.absoluteLsn < *currLsn) {
                    *currLsn = index.absoluteLsn;

                    // do not do this for every record;  hence, inside the if statement
                    flags = 0;
                    SETF(RIP_F_DATA_VALID, flags);
                    if (qsc_has_pre_emphasis(qsc)) {
                        SETF(RIP_F_DATA_PRE_EMPHASIS, flags);
                    }
                    if (qsc_has_copy_permitted(qsc)) {
                        SETF(RIP_F_DATA_COPY_PERMITTED, flags);
                    }
                    if (qsc_has_four_channels(qsc)) {
                        SETF(RIP_F_DATA_FOUR_CHANNELS, flags);
                    }
                    rip->ripData[index.track].flags = flags;
                }
            } else {
                cdio_warn("invalid index found in q sub-channel");
            }
            break;

        case QSC_MODE_MCN:
            if (!rip->mcn[0]) {
                if (qsc_get_mcn(qsc, rip->mcn)) {
                    cdio_warn("invalid mcn found in q sub-channel");
                    rip->mcn[0] = 0;
                }
            }
            break;

        case QSC_MODE_ISRC:
            isrc = rip->ripData[rip->trackHint].isrc;
            if (!isrc[0]) {
                if (qsc_get_isrc(qsc, isrc)) {
                    cdio_warn("invalid isrc found in q sub-channel");
                    isrc[0] = 0;
                } else if (!rip->year) {
                    rip->year = qsc_get_isrc_year(isrc);
                    cdio_info("set rip year to %d\n", rip->year);
                }
            }
            break;

        default:
            break;
    }
}
Exemple #29
0
/*!
  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_t *
cdio_open_os2 (const char *psz_orig_source)
{

#ifdef HAVE_OS2_CDROM
  CdIo_t *ret;
  _img_private_t *_data;
  char *psz_source;

  cdio_funcs_t _funcs;

  memset( &_funcs, 0, sizeof(_funcs) );

  _funcs.audio_get_volume       = audio_get_volume_os2;
  _funcs.audio_pause            = audio_pause_os2;
  _funcs.audio_play_msf         = audio_play_msf_os2;
#if 0
  _funcs.audio_play_track_index = audio_play_track_index_os2;
#endif
  _funcs.audio_read_subchannel  = audio_read_subchannel_os2;
  _funcs.audio_resume           = audio_resume_os2;
  _funcs.audio_set_volume       = audio_set_volume_os2;
  _funcs.audio_stop             = audio_stop_os2;
  _funcs.eject_media            = eject_media_os2;
  _funcs.free                   = free_os2;
  _funcs.get_arg                = get_arg_os2;
#if 0
  _funcs.get_blocksize          = get_blocksize_os2;
#endif
  _funcs.get_cdtext             = get_cdtext_generic;
  _funcs.get_cdtext_raw         = read_cdtext_generic;
  _funcs.get_default_device     = cdio_get_default_device_os2;
  _funcs.get_devices            = cdio_get_devices_os2;
  _funcs.get_disc_last_lsn      = get_disc_last_lsn_os2;
  _funcs.get_discmode           = get_discmode_os2;
  _funcs.get_drive_cap          = get_drive_cap_mmc;
  _funcs.get_first_track_num    = get_first_track_num_generic;
  _funcs.get_hwinfo             = NULL;
#if 0
  _funcs.get_last_session       = get_last_session_os2;
#endif
  _funcs.get_media_changed      = get_media_changed_mmc;
  _funcs.get_mcn                = _cdio_get_mcn;
  _funcs.get_num_tracks         = get_num_tracks_generic;
  _funcs.get_track_channels     = get_track_channels_generic;
  _funcs.get_track_copy_permit  = get_track_copy_permit_generic;
  _funcs.get_track_format       = _cdio_get_track_format;
  _funcs.get_track_green        = _cdio_get_track_green;
  _funcs.get_track_lba          = NULL; /* This could be done if need be. */
#if 0
  _funcs.get_track_pregap_lba   = get_track_pregap_lba_os2;
#endif
  _funcs.get_track_isrc         = _cdio_get_track_isrc;
  _funcs.get_track_msf          = _cdio_get_track_msf;
  _funcs.get_track_preemphasis  = get_track_preemphasis_generic;
  _funcs.lseek                  = cdio_generic_lseek;
  _funcs.read                   = cdio_generic_read;
  _funcs.read_audio_sectors     = read_audio_sectors_os2;
  _funcs.read_data_sectors      = read_data_sectors_mmc;
  _funcs.read_mode1_sector      = read_mode1_sector_os2;
  _funcs.read_mode1_sectors     = read_mode1_sectors_os2;
  _funcs.read_mode2_sector      = read_mode2_sector_os2;
  _funcs.read_mode2_sectors     = read_mode2_sectors_os2;
  _funcs.read_toc               = read_toc_os2;
  _funcs.run_mmc_cmd            = run_mmc_cmd_os2;
  _funcs.set_arg                = set_arg_os2;
  _funcs.set_blocksize          = set_blocksize_mmc;
  _funcs.set_speed              = set_drive_speed_mmc;

  _data                 = calloc(1, sizeof (_img_private_t));
  _data->access_mode    = _AM_OS2;
  _data->gen.b_cdtext_error = false;
  _data->gen.init       = false;
  _data->gen.fd         = -1;

  if (NULL == psz_orig_source) {
    psz_source=cdio_get_default_device_os2();
    if (NULL == psz_source) return NULL;
    set_arg_os2(_data, "source", psz_source);
    free(psz_source);
  } else {
    if (cdio_is_device_os2(psz_orig_source))
      set_arg_os2(_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
      free(_data);
      return NULL;
    }
  }

  ret = cdio_new ((void *)_data, &_funcs);
  if (ret == NULL) return NULL;

  ret->driver_id = DRIVER_OS2;

  if (init_os2(_data))
    return ret;
  else {
    free_os2 (_data);
    free(ret);
    return NULL;
  }
#else
  return NULL;
#endif /* HAVE_OS2_CDROM */

}