Ejemplo n.º 1
0
/*!
  Like fread(3) and in fact is about the same.
  
  DESCRIPTION:
  The function fread reads nmemb elements of data, each size bytes long,
  from the stream pointed to by stream, storing them at the location
  given by ptr.
  
  RETURN VALUE:
  return the number of items successfully read or written (i.e.,
  not the number of characters).  If an error occurs, or the
  end-of-file is reached, the return value is a short item count
  (or zero).
  
  We do not distinguish between end-of-file and error, and callers
  must use feof(3) and ferror(3) to determine which occurred.
  */
static long
_stdio_read(void *user_data, void *buf, long int count)
{
  _UserData *const ud = user_data;
  long read;

  read = fread(buf, 1, count, ud->fd);

  if (read != count)
    { /* fixme -- ferror/feof */
      if (feof (ud->fd))
        {
          cdio_debug ("fread (): EOF encountered");
          clearerr (ud->fd);
        }
      else if (ferror (ud->fd))
        {
          cdio_error ("fread (): %s", strerror (errno));
          clearerr (ud->fd);
        }
      else
        cdio_debug ("fread (): short read and no EOF?!?");
    }

  return read;
}
Ejemplo n.º 2
0
/*!
  Add/allocate a drive to the end of drives.
  Use cdio_free_device_list() to free this device_list.
*/
void
cdio_add_device_list(char **device_list[], const char *drive,
                     unsigned int *num_drives)
{
  if (NULL != drive) {
    unsigned int j;
    char real_device_1[PATH_MAX];
    char real_device_2[PATH_MAX];
    cdio_realpath(drive, real_device_1);
    /* Check if drive is already in list. */
    for (j=0; j<*num_drives; j++) {
      cdio_realpath((*device_list)[j], real_device_2);
      if (strcmp(real_device_1, real_device_2) == 0) break;
    }

    if (j==*num_drives) {
      /* Drive not in list. Add it. */
      (*num_drives)++;
      *device_list = realloc(*device_list, (*num_drives) * sizeof(char *));
      cdio_debug("Adding drive %s to list of devices", drive);
      (*device_list)[*num_drives-1] = strdup(drive);
      }

  } else {
    (*num_drives)++;
    if (*device_list) {
      *device_list = realloc(*device_list, (*num_drives) * sizeof(char *));
    } else {
      *device_list = malloc((*num_drives) * sizeof(char *));
    }
    cdio_debug("Adding NULL to end of drive list of size %d", (*num_drives)-1);
    (*device_list)[*num_drives-1] = NULL;
  }
}
Ejemplo n.º 3
0
/*!
   Reads a single mode1 sector from cd device into data starting from
   lsn. Returns 0 if no error.
 */
static int
read_mode1_sector_win32 (void *p_user_data, void *p_buf, lsn_t lsn, 
			 bool b_form2)
{
  _img_private_t *p_env = p_user_data;

  if (p_env->gen.ioctls_debugged == 75)
    cdio_debug ("only displaying every 75th ioctl from now on");

  if (p_env->gen.ioctls_debugged == 30 * 75)
    cdio_debug ("only displaying every 30*75th ioctl from now on");
  
  if (p_env->gen.ioctls_debugged < 75 
      || (p_env->gen.ioctls_debugged < (30 * 75)  
	  && p_env->gen.ioctls_debugged % 75 == 0)
      || p_env->gen.ioctls_debugged % (30 * 75) == 0)
    cdio_debug ("reading %lu", (unsigned long int) lsn);
  
  p_env->gen.ioctls_debugged++;

  if ( p_env->hASPI ) {
    return read_mode1_sector_aspi( p_env, p_buf, lsn, b_form2 );
  } else {
    return read_mode1_sector_win32ioctl( p_env, p_buf, lsn, b_form2 );
  }
}
Ejemplo n.º 4
0
/*!
   Reads a single mode2 sector from cd device into data starting
   from lsn. Returns 0 if no error. 
 */
static int
read_mode2_sector_win32 (void *p_user_data, void *data, lsn_t lsn, 
			 bool b_form2)
{
  char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
  _img_private_t *p_env = p_user_data;

  if (p_env->gen.ioctls_debugged == 75)
    cdio_debug ("only displaying every 75th ioctl from now on");

  if (p_env->gen.ioctls_debugged == 30 * 75)
    cdio_debug ("only displaying every 30*75th ioctl from now on");
  
  if (p_env->gen.ioctls_debugged < 75 
      || (p_env->gen.ioctls_debugged < (30 * 75)  
	  && p_env->gen.ioctls_debugged % 75 == 0)
      || p_env->gen.ioctls_debugged % (30 * 75) == 0)
    cdio_debug ("reading %lu", (unsigned long int) lsn);
  
  p_env->gen.ioctls_debugged++;

  if ( p_env->hASPI ) {
    int ret;
    ret = read_mode2_sector_aspi(p_user_data, buf, lsn, 1);
    if( ret != 0 ) return ret;
    if (b_form2)
      memcpy (data, buf, M2RAW_SECTOR_SIZE);
    else
      memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
    return 0;
  } else {
    return read_mode2_sector_win32ioctl( p_env, data, lsn, b_form2 );
  }
}
Ejemplo n.º 5
0
/* 
   Read a particular block into the global array to be used for further
   analysis later.
*/
static int 
_cdio_read_block(const CdIo *cdio, int superblock, uint32_t offset, 
		 uint8_t bufnum, track_t track_num)
{
  unsigned int track_sec_count = cdio_get_track_sec_count(cdio, track_num);
  memset(buffer[bufnum], 0, CDIO_CD_FRAMESIZE);

  if ( track_sec_count < superblock) {
    cdio_debug("reading block %u skipped track %d has only %u sectors\n", 
	       superblock, track_num, track_sec_count);
    return -1;
  }
  
  cdio_debug("about to read sector %lu\n", 
	     (long unsigned int) offset+superblock);

  if (cdio_get_track_green(cdio,  track_num)) {
    if (0 > cdio_read_mode2_sector(cdio, buffer[bufnum], 
				   offset+superblock, false))
      return -1;
  } else {
    if (0 > cdio_read_mode1_sector(cdio, buffer[bufnum], 
				    offset+superblock, false))
      return -1;
  }

  return 0;
}
Ejemplo n.º 6
0
const char *
is_cdrom_win32ioctl(const char c_drive_letter) 
{
#ifdef _XBOX
  char sz_win32_drive_full[] = "\\\\.\\X:";
  sz_win32_drive_full[4] = c_drive_letter;
  return strdup(sz_win32_drive_full);
#else
  UINT uDriveType;
  char sz_win32_drive[4];
  
  sz_win32_drive[0]= c_drive_letter;
  sz_win32_drive[1]=':';
  sz_win32_drive[2]='\\';
  sz_win32_drive[3]='\0';
  
  uDriveType = GetDriveType(sz_win32_drive);
  
  switch(uDriveType) {
  case DRIVE_CDROM: {
    char sz_win32_drive_full[] = "\\\\.\\X:";
    sz_win32_drive_full[4] = c_drive_letter;
    return strdup(sz_win32_drive_full);
  }
  default:
    cdio_debug("Drive %c is not a CD-ROM", c_drive_letter);
    return NULL;
  }
#endif
}
Ejemplo n.º 7
0
/*
   Read a particular block into the global array to be used for further
   analysis later.
*/
static driver_return_code_t
_cdio_read_block(const CdIo_t *p_cdio, int superblock, uint32_t offset,
		 uint8_t bufnum, track_t i_track)
{
  unsigned int track_sec_count = cdio_get_track_sec_count(p_cdio, i_track);
  memset(buffer[bufnum], 0, CDIO_CD_FRAMESIZE);

  if ( track_sec_count < superblock) {
    cdio_debug("reading block %u skipped track %d has only %u sectors\n",
	       superblock, i_track, track_sec_count);
    return DRIVER_OP_ERROR;
  }

  cdio_debug("about to read sector %lu\n",
	     (long unsigned int) offset+superblock);

  return cdio_read_data_sectors (p_cdio, buffer[bufnum], offset+superblock,
				 ISO_BLOCKSIZE, 1);
}
Ejemplo n.º 8
0
void
cdio_stream_close(CdioDataSource_t *p_obj)
{
  if (!p_obj) return;

  if (p_obj->is_open) {
    cdio_debug ("closed source...");
    p_obj->op.close(p_obj->user_data);
    p_obj->is_open  = 0;
    p_obj->position = 0;
  }
}
Ejemplo n.º 9
0
/*!
   Reads a single mode2 sector from cd device into data starting
   from lsn. Returns 0 if no error.
 */
static int
read_mode2_sector_win32 (void *p_user_data, void *data, lsn_t lsn,
			 bool b_form2)
{
  char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
  _img_private_t *p_env = p_user_data;

  if (p_env->gen.ioctls_debugged == 75)
    cdio_debug ("only displaying every 75th ioctl from now on");

  if (p_env->gen.ioctls_debugged == 30 * 75)
    cdio_debug ("only displaying every 30*75th ioctl from now on");

  if (p_env->gen.ioctls_debugged < 75
      || (p_env->gen.ioctls_debugged < (30 * 75)
	  && p_env->gen.ioctls_debugged % 75 == 0)
      || p_env->gen.ioctls_debugged % (30 * 75) == 0)
    cdio_debug ("reading %lu", (unsigned long int) lsn);

  p_env->gen.ioctls_debugged++;

  return read_mode2_sector_win32ioctl( p_env, data, lsn, b_form2 );
}
Ejemplo n.º 10
0
static void
_idr2statbuf (const iso9660_dir_t *idr, iso9660_stat_t *stat, bool is_mode2)
{
  iso9660_xa_t *xa_data = NULL;
  uint8_t dir_len= iso9660_get_dir_len(idr);

  memset ((void *) stat, 0, sizeof (iso9660_stat_t));

  if (!dir_len) return;

  stat->type    = (idr->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE;
  stat->lsn     = from_733 (idr->extent);
  stat->size    = from_733 (idr->size);
  stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE);

  iso9660_get_dtime(&(idr->recording_time), true, &(stat->tm));

  cdio_assert (dir_len >= sizeof (iso9660_dir_t));

  if (is_mode2) {
    int su_length = iso9660_get_dir_len(idr) - sizeof (iso9660_dir_t);
    su_length -= idr->filename_len;
    
    if (su_length % 2)
      su_length--;
    
    if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
      return;
    
    xa_data = (void *) (((char *) idr) + (iso9660_get_dir_len(idr) - su_length));
    
    if (xa_data->signature[0] != 'X' 
	|| xa_data->signature[1] != 'A')
    {
      cdio_warn ("XA signature not found in ISO9660's system use area;"
		 " ignoring XA attributes for this file entry.");
      cdio_debug ("%d %d %d, '%c%c' (%d, %d)", iso9660_get_dir_len(idr), 
		  idr->filename_len,
		  su_length,
		  xa_data->signature[0], xa_data->signature[1],
		  xa_data->signature[0], xa_data->signature[1]);
      return;
    }
    stat->xa = *xa_data;
  }
    
}
Ejemplo n.º 11
0
/*
   Open if not already open.
   Return false if we hit an error. Errno should be set for that error.
*/
static bool
_cdio_stream_open_if_necessary(CdioDataSource_t *p_obj)
{
  if (!p_obj) return false;

  if (!p_obj->is_open) {
    if (p_obj->op.open(p_obj->user_data)) {
      cdio_warn ("could not open input stream...");
      return false;
    } else {
      cdio_debug ("opened source...");
      p_obj->is_open = 1;
      p_obj->position = 0;
    }
  }
  return true;
}
Ejemplo n.º 12
0
static int
parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir,
			       iso9660_stat_t *p_stat, int regard_xa)
{
  int len;
  unsigned char * chr;
  int symlink_len = 0;
  CONTINUE_DECLS;

  if (nope == p_stat->rr.b3_rock) return 0;

  SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len);
  if (regard_xa)
    {
      chr+=14;
      len-=14;
      if (len<0) len=0;
    }
  
  /* repeat:*/
  {
    int sig;
    iso_extension_record_t * rr;
    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 = from_721(*chr);
      chr += rr->len; 
      len -= rr->len;
      
      switch(sig){
      case SIG('S','P'):
	CHECK_SP(goto out);
	break;
      case SIG('C','E'):
	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('P','X'):
	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);
	break;
      case SIG('P','N'):
	/* Device major,minor number */
	{ int32_t high, low;
	  high = from_733(rr->u.PN.dev_high);
	  low = from_733(rr->u.PN.dev_low);
	  /*
	   * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
	   * then the high field is unused, and the device number is completely
	   * stored in the low field.  Some writers may ignore this subtlety,
	   * and as a result we test to see if the entire device number is
	   * stored in the low field, and use that.
	   */
	  if((low & ~0xff) && high == 0) {
	    p_stat->rr.i_rdev = CDIO_MKDEV(low >> 8, low & 0xff);
	  } else {
	    p_stat->rr.i_rdev = CDIO_MKDEV(high, low);
	  }
	}
	break;
      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;
	}
      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++] = '/';
	      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'):
	cdio_warn("Attempt to read p_stat for relocated directory");
	goto out;
#ifdef FINISHED
      case SIG('C','L'): 
	{
	  iso9660_stat_t * reloc;
	  ISOFS_I(p_stat)->i_first_extent = from_733(rr->u.CL.location);
	  reloc = isofs_iget(p_stat->rr.i_sb, p_stat->rr.i_first_extent, 0);
	  if (!reloc)
	    goto out;
	  p_stat->rr.st_mode   = reloc->st_mode;
	  p_stat->rr.st_nlinks = reloc->st_nlinks;
	  p_stat->rr.st_uid    = reloc->st_uid;
	  p_stat->rr.st_gid    = reloc->st_gid;
	  p_stat->rr.i_rdev    = reloc->i_rdev;
	  p_stat->rr.i_symlink = reloc->i_symlink;
	  p_stat->rr.i_blocks  = reloc->i_blocks;
	  p_stat->rr.i_atime   = reloc->i_atime;
	  p_stat->rr.i_ctime   = reloc->i_ctime;
	  p_stat->rr.i_mtime   = reloc->i_mtime;
	  iput(reloc);
	}
	break;
#endif
      default:
	break;
      }
    }
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
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_am_win32 (const char *psz_orig_source, const char *psz_access_mode)
{

#ifdef HAVE_WIN32_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_win32;
  _funcs.audio_pause            = audio_pause_win32;
  _funcs.audio_play_msf         = audio_play_msf_win32;
#if 0
  _funcs.audio_play_track_index = audio_play_track_index_win32;
#endif
  _funcs.audio_read_subchannel  = audio_read_subchannel_win32;
  _funcs.audio_resume           = audio_resume_win32;
  _funcs.audio_set_volume       = audio_set_volume_win32;
  _funcs.audio_stop             = audio_stop_win32;
  _funcs.eject_media            = eject_media_win32;
  _funcs.free                   = free_win32;
  _funcs.get_arg                = get_arg_win32;
  _funcs.get_cdtext             = get_cdtext_generic;
  _funcs.get_cdtext_raw         = read_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_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. */
  _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     = read_audio_sectors;
  _funcs.read_data_sectors      = read_data_sectors_win32;
  _funcs.read_mode1_sector      = read_mode1_sector_win32;
  _funcs.read_mode1_sectors     = read_mode1_sectors_win32;
  _funcs.read_mode2_sector      = read_mode2_sector_win32;
  _funcs.read_mode2_sectors     = read_mode2_sectors_win32;
  _funcs.read_toc               = read_toc_win32;
  _funcs.run_mmc_cmd            = run_mmc_cmd_win32;
  _funcs.set_arg                = set_arg_win32;
  _funcs.set_blocksize          = set_blocksize_mmc;
  _funcs.set_speed              = set_drive_speed_mmc;

  _data                 = calloc(1, 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 as an info message if all device
	 drivers worked this way. */
      cdio_debug ("source %s is a not a device", psz_orig_source);
      free(_data);
      return NULL;
    }
  }

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

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

}
Ejemplo n.º 15
0
/*!
  Initialize internal structures for CD device.
 */
bool
init_win32ioctl (_img_private_t *env)
{
#ifdef WIN32
  OSVERSIONINFO ov;
#endif

#ifdef _XBOX
  ANSI_STRING filename;
  OBJECT_ATTRIBUTES attributes;
  IO_STATUS_BLOCK status;
  HANDLE hDevice;
  NTSTATUS error;
#else
  unsigned int len=strlen(env->gen.source_name);
  char psz_win32_drive[7];
  DWORD dw_access_flags;
#endif
  
  cdio_debug("using winNT/2K/XP ioctl layer");

#ifdef WIN32
  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;
#endif

  if (cdio_is_device_win32(env->gen.source_name)) 
  {
#ifdef _XBOX
    //	Use XBOX cdrom, no matter what drive letter is given.
    RtlInitAnsiString(&filename,"\\Device\\Cdrom0");
    InitializeObjectAttributes(&attributes, &filename, OBJ_CASE_INSENSITIVE,
			       NULL);
    error = NtCreateFile( &hDevice, 
			  GENERIC_READ |SYNCHRONIZE | FILE_READ_ATTRIBUTES, 
			  &attributes, 
			  &status, 
			  NULL, 
			  0,
			  FILE_SHARE_READ,
			  FILE_OPEN,	
			  FILE_NON_DIRECTORY_FILE 
			  | FILE_SYNCHRONOUS_IO_NONALERT );
    
    if (!NT_SUCCESS(error))
    {
	  return false;
    }
	env->h_device_handle = hDevice;
#else
    sprintf( psz_win32_drive, "\\\\.\\%c:", env->gen.source_name[len-2] );

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

    if( env->h_device_handle == INVALID_HANDLE_VALUE )
    {
	  /* No good. try toggle write. */
	  dw_access_flags ^= GENERIC_WRITE;  
	  env->h_device_handle = CreateFile( psz_win32_drive, 
					     dw_access_flags, 
					     FILE_SHARE_READ,  
					     NULL, 
					     OPEN_EXISTING, 
					     FILE_ATTRIBUTE_NORMAL, 
					     NULL );
	  if (env->h_device_handle == NULL)
		return false;
    }
#endif
    env->b_ioctl_init = true;
    return true;
  }
  return false;
}
Ejemplo n.º 16
0
/*!  
  Read and cache the CD's Track Table of Contents and track info.
  via a SCSI MMC READ_TOC (FULTOC).  Return true if successful or
  false if an error.
*/
static bool
read_fulltoc_win32mmc (_img_private_t *p_env) 
{
  mmc_cdb_t  cdb = {{0, }};
  CDROM_TOC_FULL  cdrom_toc_full;
  int             i_status, i, j;
  int             i_track_format = 0;
  int             i_seen_flag;

  /* Operation code */
  CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);

  cdb.field[1] = 0x00;

  /* Format */
  cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC;

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

  /* Setup to read header, to get length of data */
  CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(cdrom_toc_full));

  i_status = run_mmc_cmd_win32ioctl (p_env, 1000*60*3,
				     mmc_get_cmd_len(cdb.field[0]), 
				     &cdb, SCSI_MMC_DATA_READ, 
				     sizeof(cdrom_toc_full), &cdrom_toc_full);

  if ( 0 != i_status ) {
    cdio_debug ("SCSI MMC READ_TOC failed\n");  
    return false;
  } 
    
  i_seen_flag=0;
  for( i = 0 ; i <= CDIO_CD_MAX_TRACKS+3; i++ ) {
    
    if ( 0xA0 == cdrom_toc_full.TrackData[i].POINT ) { 
      /* First track number */
      p_env->gen.i_first_track = cdrom_toc_full.TrackData[i].PMIN;
      i_track_format = cdrom_toc_full.TrackData[i].PSEC;
      i_seen_flag|=0x01;
    }
    
    if ( 0xA1 == cdrom_toc_full.TrackData[i].POINT ) { 
      /* Last track number */
      p_env->gen.i_tracks = 
	cdrom_toc_full.TrackData[i].PMIN - p_env->gen.i_first_track + 1;
      i_seen_flag|=0x02;
    }

    j = cdrom_toc_full.TrackData[i].POINT;
    if ( 0xA2 ==  j ) { 
      /* Start position of the lead out */
      p_env->tocent[ p_env->gen.i_tracks ].start_lsn = 
	cdio_lba_to_lsn(
			cdio_msf3_to_lba(
					 cdrom_toc_full.TrackData[i].PMIN,
					 cdrom_toc_full.TrackData[i].PSEC,
					 cdrom_toc_full.TrackData[i].PFRAME 
					 )
			);
      p_env->tocent[ p_env->gen.i_tracks ].Control 
	= cdrom_toc_full.TrackData[i].Control;
      p_env->tocent[ p_env->gen.i_tracks ].Format  = i_track_format;
      i_seen_flag|=0x04;
    }
    
    if (cdrom_toc_full.TrackData[i].POINT > 0 
	&& cdrom_toc_full.TrackData[i].POINT <= p_env->gen.i_tracks) {
      p_env->tocent[j-1].start_lsn = 
	cdio_lba_to_lsn(
			cdio_msf3_to_lba(
					 cdrom_toc_full.TrackData[i].PMIN,
					 cdrom_toc_full.TrackData[i].PSEC,
					 cdrom_toc_full.TrackData[i].PFRAME 
					 )
			);
      p_env->tocent[j-1].Control = 
	cdrom_toc_full.TrackData[i].Control;
      p_env->tocent[j-1].Format  = i_track_format;
      
      set_track_flags(&(p_env->gen.track_flags[j]), 
		      p_env->tocent[j-1].Control);
    
      cdio_debug("p_sectors: %i, %lu", i, 
		 (unsigned long int) (p_env->tocent[i].start_lsn));
      
      if (cdrom_toc_full.TrackData[i].POINT == p_env->gen.i_tracks)
	i_seen_flag|=0x08;
    }
    
    if ( 0x0F == i_seen_flag ) break;
  }
  if ( 0x0F == i_seen_flag ) {
    p_env->gen.toc_init = true; 
    return true;
  }
  return false;
}
Ejemplo n.º 17
0
static iso9660_stat_t *
_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, 
			 uint8_t i_joliet_level)
{
  uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
  iso711_t i_fname;
  unsigned int stat_len;
  iso9660_stat_t *p_stat;

  if (!dir_len) return NULL;

  i_fname  = from_711(p_iso9660_dir->filename_len);

  /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */
  stat_len      = sizeof(iso9660_stat_t)+i_fname+2;

  p_stat          = calloc(1, stat_len);
  if (!p_stat)
    {
    cdio_warn("Couldn't calloc(1, %d)", stat_len);
    return NULL;
    }
  p_stat->type    = (p_iso9660_dir->file_flags & ISO_DIRECTORY) 
    ? _STAT_DIR : _STAT_FILE;
  p_stat->lsn     = from_733 (p_iso9660_dir->extent);
  p_stat->size    = from_733 (p_iso9660_dir->size);
  p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE);
  p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */
  p_stat->b_xa    = false; 

  {
    char rr_fname[256] = "";

    int  i_rr_fname = 
#ifdef HAVE_ROCK
      get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat);
#else
      0;
#endif
    
    if (i_rr_fname > 0) {
      if (i_rr_fname > i_fname) {
	/* realloc gives valgrind errors */
	iso9660_stat_t *p_stat_new = 
	  calloc(1, sizeof(iso9660_stat_t)+i_rr_fname+2);
        if (!p_stat_new)
          {
          cdio_warn("Couldn't calloc(1, %d)", sizeof(iso9660_stat_t)+i_rr_fname+2);
          return NULL;
          }
	memcpy(p_stat_new, p_stat, stat_len);
	free(p_stat);
	p_stat = p_stat_new;
      }
      strncpy(p_stat->filename, rr_fname, i_rr_fname+1);
    } else {
      if ('\0' == p_iso9660_dir->filename[0] && 1 == i_fname)
	strncpy (p_stat->filename, ".", sizeof("."));
      else if ('\1' == p_iso9660_dir->filename[0] && 1 == i_fname)
	strncpy (p_stat->filename, "..", sizeof(".."));
#ifdef HAVE_JOLIET
      else if (i_joliet_level) {
	int i_inlen = i_fname;
	cdio_utf8_t *p_psz_out = NULL;
	if (cdio_charset_to_utf8(p_iso9660_dir->filename, i_inlen,
                             &p_psz_out, "UCS-2BE")) {
          strncpy(p_stat->filename, p_psz_out, i_fname);
          free(p_psz_out);
        }
        else {
          return NULL;
        }
      }
#endif /*HAVE_JOLIET*/
      else {
	strncpy (p_stat->filename, p_iso9660_dir->filename, i_fname);
      }
    }
  }
  

  iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm));

  if (dir_len < sizeof (iso9660_dir_t)) {
    free(p_stat->rr.psz_symlink);
    free(p_stat);
    return NULL;
  }
  

  {
    int su_length = iso9660_get_dir_len(p_iso9660_dir) 
      - sizeof (iso9660_dir_t);
    su_length -= i_fname;
    
    if (su_length % 2)
      su_length--;
    
    if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
      return p_stat;
    
    if (nope == b_xa) {
      return p_stat;
    } else {
      iso9660_xa_t *xa_data = 
	(void *) (((char *) p_iso9660_dir)  
		  + (iso9660_get_dir_len(p_iso9660_dir) - su_length));
      cdio_log_level_t loglevel = (yep == b_xa) 
	? CDIO_LOG_WARN : CDIO_LOG_INFO;
      
      if (xa_data->signature[0] != 'X' 
	  || xa_data->signature[1] != 'A')
	{
	  cdio_log (loglevel, 
		    "XA signature not found in ISO9660's system use area;"
		     " ignoring XA attributes for this file entry.");
	  cdio_debug ("%d %d %d, '%c%c' (%d, %d)", 
		      iso9660_get_dir_len(p_iso9660_dir), 
		      i_fname,
		      su_length,
		      xa_data->signature[0], xa_data->signature[1],
		      xa_data->signature[0], xa_data->signature[1]);
	  return p_stat;
	}
      p_stat->b_xa = true;
      p_stat->xa   = *xa_data;
    }
  }
  return p_stat;
    
}
Ejemplo n.º 18
0
/*! 
  Read and cache the CD's Track Table of Contents and track info.
  Return true if successful or false if an error.
*/
bool
read_toc_win32ioctl (_img_private_t *p_env) 
{
  CDROM_TOC    cdrom_toc;
  DWORD        dw_bytes_returned;
  unsigned int i, j;
  bool         b_fulltoc_first;  /* Do we do fulltoc or DeviceIoControl 
				    first? */
  if ( ! p_env ) return false;

  /* 
     The MMC5 spec says:
       For media other than CD, information may be fabricated in order
                                            ^^^ ^^
       to emulate a CD structure for the specific media.

     There is no requirement though that it *has* to and some DVD
     drives like one by Thompson for XBOX don't support a
     IOCTL_CDROM_READ_TOC for DVD's. So if we have a DVD we should not
     prefer getting the TOC via MMC.

     But on the other hand in GNU/Linux it is reported that using the
     TOC via MMC gives better information such as for CD DATA Form 2 (used
     in SVCDs). So if we *don't* have a DVD I think we want to try MMC
     first. 

     Is this complicated enough? I could be wrong...

   */
  b_fulltoc_first = (CDIO_DISC_MODE_NO_INFO == dvd_discmode_win32ioctl(p_env));

  if ( b_fulltoc_first && read_fulltoc_win32mmc(p_env) ) return true;

  /* SCSI-MMC READ_TOC (FULTOC) read failed or we don't want to try it
     initiaily.  Try reading TOC via DeviceIoControl... */

  if( DeviceIoControl( p_env->h_device_handle,
		       IOCTL_CDROM_READ_TOC,
		       NULL, 0, &cdrom_toc, sizeof(CDROM_TOC),
		       &dw_bytes_returned, NULL ) == 0 ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    cdio_log_level_t loglevel = b_fulltoc_first 
      ? CDIO_LOG_WARN : CDIO_LOG_DEBUG;

    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) {
      cdio_log(loglevel, "could not read TOC (%ld): %s", i_err, psz_msg);
      LocalFree(psz_msg);
    } else 
      cdio_log(loglevel, "could not read TOC (%ld)", i_err);

    if ( !b_fulltoc_first && read_fulltoc_win32mmc(p_env) ) return true;
    return false;
  }
  
  p_env->gen.i_first_track = cdrom_toc.FirstTrack;
  p_env->gen.i_tracks  = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;

  j = p_env->gen.i_first_track;
  for( i = 0 ; i <= p_env->gen.i_tracks ; i++, j++ ) {
    p_env->tocent[ i ].start_lsn = 
      cdio_lba_to_lsn(
		      cdio_msf3_to_lba( cdrom_toc.TrackData[i].Address[1],
					cdrom_toc.TrackData[i].Address[2],
					cdrom_toc.TrackData[i].Address[3] )
		      );
    p_env->tocent[i].Control   = cdrom_toc.TrackData[i].Control;
    p_env->tocent[i].Format    = cdrom_toc.TrackData[i].Adr;

    p_env->gen.track_flags[j].preemphasis = 
      p_env->tocent[i].Control & 0x1 
      ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;

    p_env->gen.track_flags[j].copy_permit = 
      p_env->tocent[i].Control & 0x2 
      ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
    
    p_env->gen.track_flags[j].channels = 
      p_env->tocent[i].Control & 0x8 ? 4 : 2;
    

    cdio_debug("p_sectors: %i, %lu", i, 
	       (unsigned long int) (p_env->tocent[i].start_lsn));
  }
  p_env->gen.toc_init = true;
  return true;
}
Ejemplo n.º 19
0
static iso9660_stat_t *
_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, 
			 bool b_mode2, uint8_t i_joliet_level)
{
  iso9660_xa_t *xa_data = NULL;
  uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
  unsigned int filename_len;
  unsigned int stat_len;
  iso9660_stat_t *stat;

  if (!dir_len) return NULL;

  filename_len  = from_711(p_iso9660_dir->filename_len);

  /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */
  stat_len      = sizeof(iso9660_stat_t)+filename_len+2;

  stat          = _cdio_malloc(stat_len);
  stat->type    = (p_iso9660_dir->file_flags & ISO_DIRECTORY) 
    ? _STAT_DIR : _STAT_FILE;
  stat->lsn     = from_733 (p_iso9660_dir->extent);
  stat->size    = from_733 (p_iso9660_dir->size);
  stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE);

  if ('\0' == p_iso9660_dir->filename[0] && 1 == filename_len)
    strcpy (stat->filename, ".");
	else if ('\1' == p_iso9660_dir->filename[0] && 1 == filename_len)
    strcpy (stat->filename, "..");
  else {
#ifdef HAVE_JOLIET
    if (i_joliet_level) {
      int i_inlen = filename_len;
      int i_outlen = (i_inlen / 2);
      char *p_psz_out = NULL;
      ucs2be_to_locale(p_iso9660_dir->filename, i_inlen, 
		       &p_psz_out, i_outlen);
      strncpy(stat->filename, p_psz_out, filename_len);
      free(p_psz_out);
    } else
#endif /*HAVE_JOLIET*/
      strncpy (stat->filename, p_iso9660_dir->filename, filename_len);
  }


  iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm));

  cdio_assert (dir_len >= sizeof (iso9660_dir_t));

  if (b_mode2) {
    int su_length = iso9660_get_dir_len(p_iso9660_dir) 
      - sizeof (iso9660_dir_t);
    su_length -= filename_len;
    
    if (su_length % 2)
      su_length--;
    
    if (su_length < 0 || su_length < sizeof (iso9660_xa_t))
      return stat;
    
    xa_data = (void *) (((char *) p_iso9660_dir) 
			+ (iso9660_get_dir_len(p_iso9660_dir) - su_length));
    
    if (xa_data->signature[0] != 'X' 
	|| xa_data->signature[1] != 'A')
    {
      cdio_warn ("XA signature not found in ISO9660's system use area;"
		 " ignoring XA attributes for this file entry.");
      cdio_debug ("%d %d %d, '%c%c' (%d, %d)", 
		  iso9660_get_dir_len(p_iso9660_dir), 
		  filename_len,
		  su_length,
		  xa_data->signature[0], xa_data->signature[1],
		  xa_data->signature[0], xa_data->signature[1]);
      return stat;
    }
    stat->xa = *xa_data;
  }
  return stat;
    
}
Ejemplo n.º 20
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_cdrdao (const char *psz_cue_name)
{
  CdIo_t *ret;
  _img_private_t *p_data;

  cdio_funcs_t _funcs;

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

  _funcs.eject_media           = _eject_media_image;
  _funcs.free                  = _free_image;
  _funcs.get_arg               = _get_arg_image;
  _funcs.get_cdtext            = _get_cdtext_image;
  _funcs.get_cdtext_raw        = NULL;
  _funcs.get_devices           = cdio_get_devices_cdrdao;
  _funcs.get_default_device    = cdio_get_default_device_cdrdao;
  _funcs.get_disc_last_lsn     = get_disc_last_lsn_cdrdao;
  _funcs.get_discmode          = _get_discmode_image;
  _funcs.get_drive_cap         = _get_drive_cap_image;
  _funcs.get_first_track_num   = _get_first_track_num_image;
  _funcs.get_hwinfo            = get_hwinfo_cdrdao;
  _funcs.get_media_changed     = get_media_changed_image;
  _funcs.get_mcn               = _get_mcn_image;
  _funcs.get_num_tracks        = _get_num_tracks_image;
  _funcs.get_track_channels    = get_track_channels_image;
  _funcs.get_track_copy_permit = get_track_copy_permit_image;
  _funcs.get_track_format      = _get_track_format_cdrdao;
  _funcs.get_track_green       = _get_track_green_cdrdao;
  _funcs.get_track_lba         = _get_lba_track_cdrdao;
  _funcs.get_track_msf         = _get_track_msf_image;
  _funcs.get_track_preemphasis = get_track_preemphasis_image;
  _funcs.get_track_pregap_lba  = get_track_pregap_lba_image;
  _funcs.get_track_isrc        = get_track_isrc_image;
  _funcs.lseek                 = _lseek_cdrdao;
  _funcs.read                  = _read_cdrdao;
  _funcs.read_audio_sectors    = _read_audio_sectors_cdrdao;
  _funcs.read_data_sectors     = read_data_sectors_image;
  _funcs.read_mode1_sector     = _read_mode1_sector_cdrdao;
  _funcs.read_mode1_sectors    = _read_mode1_sectors_cdrdao;
  _funcs.read_mode2_sector     = _read_mode2_sector_cdrdao;
  _funcs.read_mode2_sectors    = _read_mode2_sectors_cdrdao;
  _funcs.run_mmc_cmd           = NULL;
  _funcs.set_arg               = _set_arg_image;
  _funcs.set_speed             = cdio_generic_unimplemented_set_speed;
  _funcs.set_blocksize         = cdio_generic_unimplemented_set_blocksize;

  if (NULL == psz_cue_name) return NULL;

  p_data                  = calloc(1, sizeof (_img_private_t));
  p_data->gen.init        = false;
  p_data->psz_cue_name    = NULL;
  p_data->gen.data_source = NULL;
  p_data->gen.source_name = NULL;

  ret = cdio_new ((void *)p_data, &_funcs);

  if (ret == NULL) {
    free(p_data);
    return NULL;
  }

  ret->driver_id = DRIVER_CDRDAO;
  if (!cdio_is_tocfile(psz_cue_name)) {
    cdio_debug ("source name %s is not recognized as a TOC file",
		psz_cue_name);
    free(p_data);
    free(ret);
    return NULL;
  }

  _set_arg_image (p_data, "cue", psz_cue_name);
  _set_arg_image (p_data, "source", psz_cue_name);
  _set_arg_image (p_data, "access-mode", "cdrdao");

  if (_init_cdrdao(p_data)) {
    return ret;
  } else {
    _free_image(p_data);
    free(ret);
    return NULL;
  }
}
Ejemplo n.º 21
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);
    }
Ejemplo n.º 22
0
/* Updates internal track TOC, so we can later 
   simulate ioctl(CDROMREADTOCENTRY).
 */
static void
_register_mapping (_img_private_t *env, lsn_t start_lsn, uint32_t sec_count,
		   uint64_t img_offset, uint32_t blocksize,
		   track_format_t track_format, bool track_green)
{
  const int track_num=env->gen.i_tracks;
  track_info_t  *this_track=&(env->tocent[env->gen.i_tracks]);
  _mapping_t *_map = calloc(1, sizeof (_mapping_t));

  _map->start_lsn  = start_lsn;
  _map->sec_count  = sec_count;
  _map->img_offset = img_offset;
  _map->blocksize  = blocksize;

  if (!env->mapping) env->mapping = _cdio_list_new ();
  _cdio_list_append (env->mapping, _map);

  env->size = MAX (env->size, (start_lsn + sec_count));

  /* Update *this_track and track_num. These structures are
     in a sense redundant witht the obj->mapping list. Perhaps one
     or the other can be eliminated.
   */

  cdio_lba_to_msf (cdio_lsn_to_lba(start_lsn), &(this_track->start_msf));
  this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf);
  this_track->track_num = track_num+1;
  this_track->blocksize = blocksize;
  if (env->is_cues) 
    this_track->datastart = img_offset;
  else 
    this_track->datastart = 0;

  if (track_green) 
    this_track->datastart += CDIO_CD_SUBHEADER_SIZE;
      
  this_track->sec_count = sec_count;

  this_track->track_format= track_format;
  this_track->track_green = track_green;

  switch (this_track->track_format) {
  case TRACK_FORMAT_AUDIO:
    this_track->blocksize   = CDIO_CD_FRAMESIZE_RAW;
    this_track->datasize    = CDIO_CD_FRAMESIZE_RAW;
    /*this_track->datastart   = 0;*/
    this_track->endsize     = 0;
    break;
  case TRACK_FORMAT_CDI:
    this_track->datasize=CDIO_CD_FRAMESIZE;
    break;
  case TRACK_FORMAT_XA:
    if (track_green) {
      this_track->blocksize = CDIO_CD_FRAMESIZE;
      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/
      this_track->datasize  = M2RAW_SECTOR_SIZE;
      this_track->endsize   = 0;
    } else {
      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +
	CDIO_CD_SUBHEADER_SIZE;*/
      this_track->datasize  = CDIO_CD_FRAMESIZE;
      this_track->endsize   = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE;
    }
    break;
  case TRACK_FORMAT_DATA:
    if (track_green) {
      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/
      this_track->datasize  = CDIO_CD_FRAMESIZE;
      this_track->endsize   = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE 
	  + CDIO_CD_ECC_SIZE;
    } else {
      /* Is the below correct? */
      /*this_track->datastart = 0;*/
      this_track->datasize  = CDIO_CD_FRAMESIZE;
      this_track->endsize   = 0;  
    }
    break;
  default:
    /*this_track->datasize=CDIO_CD_FRAMESIZE_RAW;*/
    cdio_warn ("track %d has unknown format %d",
	       env->gen.i_tracks, this_track->track_format);
  }
  
  env->gen.i_tracks++;

  cdio_debug ("start lsn: %lu sector count: %0lu -> %8ld (%08lx)", 
	      (long unsigned int) start_lsn, 
	      (long unsigned int) sec_count, 
	      (long unsigned int) img_offset,
	      (long unsigned int) img_offset);
}