Exemplo n.º 1
0
/*!
  Open an ISO 9660 image for reading. Maybe in the future we will have
  a mode. NULL is returned on error.
*/
iso9660_t *
iso9660_open_ext (const char *pathname,
		  iso_extension_mask_t iso_extension_mask)
{
  iso9660_t *p_iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ;

  if (NULL == p_iso) return NULL;
  
  p_iso->stream = cdio_stdio_new( pathname );
  if (NULL == p_iso->stream) 
    goto error;
  
  if ( !iso9660_ifs_read_superblock(p_iso, iso_extension_mask) )
    goto error;
  
  /* Determine if image has XA attributes. */
  
  p_iso->b_xa = !strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET, 
			  ISO_XA_MARKER_STRING, 
			  strlen (ISO_XA_MARKER_STRING));
  p_iso->iso_extension_mask = iso_extension_mask;
  return p_iso;

 error:
  free(p_iso);
  return NULL;
}
Exemplo n.º 2
0
/*!
  Open an ISO 9660 image for reading in either fuzzy mode or not.
*/
static iso9660_t *
iso9660_open_ext_private (const char *psz_path,
			  iso_extension_mask_t iso_extension_mask,
			  uint16_t i_fuzz, bool b_fuzzy)
{
  iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(iso9660_t)) ;
  bool b_have_superblock;

  if (!p_iso) return NULL;
  
  p_iso->stream = cdio_stdio_new( psz_path );
  if (NULL == p_iso->stream) 
    goto error;

  p_iso->i_framesize = ISO_BLOCKSIZE;

  b_have_superblock = (b_fuzzy) 
    ? iso9660_ifs_fuzzy_read_superblock(p_iso, iso_extension_mask, i_fuzz)
    : iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ;

  if ( ! b_have_superblock ) goto error;
  
  /* Determine if image has XA attributes. */
  
  p_iso->b_xa = strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET, 
			 ISO_XA_MARKER_STRING,
			 sizeof (ISO_XA_MARKER_STRING)) 
    ? nope : yep;
  
  p_iso->iso_extension_mask = iso_extension_mask;
  return p_iso;

 error:
  if (p_iso && p_iso->stream) {
    cdio_stdio_destroy(p_iso->stream);
    free(p_iso);
  }
  return NULL;
}
Exemplo n.º 3
0
static bool
parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
{
  /* The below declarations may be common in other image-parse routines. */
  FILE        *fp;
  char         psz_line[MAXLINE];   /* text of current line read in file fp. */
  unsigned int i_line=0;            /* line number in file of psz_line. */
  int          i = -1;              /* Position in tocent. Same as
				       cd->gen.i_tracks - 1 */
  char *psz_keyword, *psz_field, *psz_cue_name_dup;
  cdio_log_level_t log_level = (cd) ? CDIO_LOG_WARN : CDIO_LOG_INFO ;
  cdtext_field_t cdtext_key;

  /* The below declaration(s) may be unique to this image-parse routine. */
  unsigned int i_cdtext_nest = 0;

  if (NULL == psz_cue_name)
    return false;

  psz_cue_name_dup = _cdio_strdup_fixpath(psz_cue_name);
  if (NULL == psz_cue_name_dup)
    return false;

  fp = CDIO_FOPEN (psz_cue_name_dup, "r");
  cdio_free(psz_cue_name_dup);
  if (fp == NULL) {
    cdio_log(log_level, "error opening %s for reading: %s",
	     psz_cue_name, strerror(errno));
    return false;
  }

  if (cd) {
    cd->gen.b_cdtext_error = false;
  }

  while (fgets(psz_line, MAXLINE, fp)) {

    i_line++;

    /* strip comment from line */
    /* todo: // in quoted strings? */
    /* //comment */
    if ((psz_field = strstr (psz_line, "//")))
      *psz_field = '\0';

    if ((psz_keyword = strtok (psz_line, " \t\n\r"))) {
      /* CATALOG "ddddddddddddd" */
      if (0 == strcmp ("CATALOG", psz_keyword)) {
	if (-1 == i) {
	  if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) {
	    if (13 != strlen(psz_field)) {
	      cdio_log(log_level,
		       "%s line %d after word CATALOG:",
		       psz_cue_name, i_line);
	      cdio_log(log_level,
		       "Token %s has length %ld. Should be 13 digits.",
		       psz_field, (long int) strlen(psz_field));

	      goto err_exit;
	    } else {
	      /* Check that we have all digits*/
	      unsigned int j;
	      for (j=0; j<13; j++) {
		if (!isdigit((unsigned char) psz_field[j])) {
		    cdio_log(log_level,
			     "%s line %d after word CATALOG:",
			     psz_cue_name, i_line);
		    cdio_log(log_level,
			     "Character \"%c\" at postition %i of token \"%s\""
			     " is not all digits.",
			     psz_field[j], j+1, psz_field);
		    goto err_exit;
		}
	      }
	      if (NULL != cd) cd->psz_mcn = strdup (psz_field);
	    }
	  } else {
	    cdio_log(log_level,
		     "%s line %d after word CATALOG:",
		     psz_cue_name, i_line);
	    cdio_log(log_level, "Expecting 13 digits; nothing seen.");
	    goto err_exit;
	  }
	} else {
	  goto err_exit;
	}

	/* CD_DA | CD_ROM | CD_ROM_XA */
      } else if (0 == strcmp ("CD_DA", psz_keyword)) {
	if (-1 == i) {
	  if (NULL != cd)
	    cd->disc_mode = CDIO_DISC_MODE_CD_DA;
	} else {
	  goto not_in_global_section;
	}
      } else if (0 == strcmp ("CD_ROM", psz_keyword)) {
	if (-1 == i) {
	  if (NULL != cd)
	    cd->disc_mode = CDIO_DISC_MODE_CD_DATA;
	} else {
	  goto not_in_global_section;
	}

      } else if (0 == strcmp ("CD_ROM_XA", psz_keyword)) {
	if (-1 == i) {
	  if (NULL != cd)
	    cd->disc_mode = CDIO_DISC_MODE_CD_XA;
	} else {
	  goto not_in_global_section;
	}

	/* TRACK <track-mode> [<sub-channel-mode>] */
      } else if (0 == strcmp ("TRACK", psz_keyword)) {
	i++;
	if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	  if (0 == strcmp ("AUDIO", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_AUDIO;
	      cd->tocent[i].blocksize    = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datasize     = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datastart    = 0;
	      cd->tocent[i].endsize      = 0;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_DA;
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DATA:
	      case CDIO_DISC_MODE_CD_XA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }

	    }
	  } else if (0 == strcmp ("MODE1", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_DATA;
	      cd->tocent[i].blocksize    = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datastart    = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_HEADER_SIZE;
	      cd->tocent[i].datasize     = CDIO_CD_FRAMESIZE;
	      cd->tocent[i].endsize      = CDIO_CD_EDC_SIZE
		+ CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_DATA;
		break;
	      case CDIO_DISC_MODE_CD_DATA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_XA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE1_RAW", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_DATA;
	      cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_HEADER_SIZE;
	      cd->tocent[i].datasize  = CDIO_CD_FRAMESIZE;
	      cd->tocent[i].endsize   = CDIO_CD_EDC_SIZE
		+ CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_DATA;
		break;
	      case CDIO_DISC_MODE_CD_DATA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_XA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE2", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_XA;
	      cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_HEADER_SIZE;
	      cd->tocent[i].datasize = M2RAW_SECTOR_SIZE;
	      cd->tocent[i].endsize   = 0;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_XA;
		break;
	      case CDIO_DISC_MODE_CD_XA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_DATA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE2_FORM1", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_XA;
	      cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_HEADER_SIZE;
	      cd->tocent[i].datasize  = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].endsize   = 0;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_XA;
		break;
	      case CDIO_DISC_MODE_CD_XA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_DATA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE2_FORM2", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_XA;
	      cd->tocent[i].datastart    = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
	      cd->tocent[i].datasize     = CDIO_CD_FRAMESIZE;
	      cd->tocent[i].endsize      = CDIO_CD_SYNC_SIZE
		+ CDIO_CD_ECC_SIZE;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_XA;
		break;
	      case CDIO_DISC_MODE_CD_XA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_DATA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE2_FORM_MIX", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_XA;
	      cd->tocent[i].datasize     = M2RAW_SECTOR_SIZE;
	      cd->tocent[i].blocksize    = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datastart    = CDIO_CD_SYNC_SIZE +
		CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
	      cd->tocent[i].track_green  = true;
	      cd->tocent[i].endsize      = 0;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_XA;
		break;
	      case CDIO_DISC_MODE_CD_XA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_DATA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else if (0 == strcmp ("MODE2_RAW", psz_field)) {
	    if (NULL != cd) {
	      cd->tocent[i].track_format = TRACK_FORMAT_XA;
	      cd->tocent[i].blocksize    = CDIO_CD_FRAMESIZE_RAW;
	      cd->tocent[i].datastart    = CDIO_CD_SYNC_SIZE +
		CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;
	      cd->tocent[i].datasize     = CDIO_CD_FRAMESIZE;
	      cd->tocent[i].track_green  = true;
	      cd->tocent[i].endsize      = 0;
	      switch(cd->disc_mode) {
	      case CDIO_DISC_MODE_NO_INFO:
		cd->disc_mode = CDIO_DISC_MODE_CD_XA;
		break;
	      case CDIO_DISC_MODE_CD_XA:
	      case CDIO_DISC_MODE_CD_MIXED:
	      case CDIO_DISC_MODE_ERROR:
		/* Disc type stays the same. */
		break;
	      case CDIO_DISC_MODE_CD_DA:
	      case CDIO_DISC_MODE_CD_DATA:
		cd->disc_mode = CDIO_DISC_MODE_CD_MIXED;
		break;
	      default:
		cd->disc_mode = CDIO_DISC_MODE_ERROR;
	      }
	    }
	  } else {
	    cdio_log(log_level, "%s line %d after TRACK:",
		     psz_cue_name, i_line);
	    cdio_log(log_level, "'%s' not a valid mode.", psz_field);
	    goto err_exit;
	  }
	}
	if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	  /* \todo: set sub-channel-mode */
#ifdef TODO
	  if (0 == strcmp ("RW", psz_field))
	    ;
	  else if (0 == strcmp ("RW_RAW", psz_field))
	    ;
#endif
	}
	if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	  goto format_error;
	}

	/* track flags */
	/* [NO] COPY | [NO] PRE_EMPHASIS */
      } else if (0 == strcmp ("NO", psz_keyword)) {
	if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	  if (0 == strcmp ("COPY", psz_field)) {
	    if (NULL != cd)
	      cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED;

	  } else if (0 == strcmp ("PRE_EMPHASIS", psz_field))
	    if (NULL != cd) {
	      cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_PRE_EMPHASIS;
	    }
	} else {
	  goto format_error;
	}
	if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	  goto format_error;
	}
      } else if (0 == strcmp ("COPY", psz_keyword)) {
	if (NULL != cd && i >= 0)
	  cd->tocent[i].flags |= CDIO_TRACK_FLAG_COPY_PERMITTED;
      } else if (0 == strcmp ("PRE_EMPHASIS", psz_keyword)) {
	if (NULL != cd && i >= 0)
	  cd->tocent[i].flags |= CDIO_TRACK_FLAG_PRE_EMPHASIS;
	/* TWO_CHANNEL_AUDIO */
      } else if (0 == strcmp ("TWO_CHANNEL_AUDIO", psz_keyword)) {
	if (NULL != cd && i >= 0)
	  cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO;
	/* FOUR_CHANNEL_AUDIO */
      } else if (0 == strcmp ("FOUR_CHANNEL_AUDIO", psz_keyword)) {
	if (NULL != cd && i >= 0)
	  cd->tocent[i].flags |= CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO;

	/* ISRC "CCOOOYYSSSSS" */
      } else if (0 == strcmp ("ISRC", psz_keyword)) {
	if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) {
	  if (NULL != cd)
	    cd->tocent[i].isrc = strdup(psz_field);
	} else {
	  goto format_error;
	}

	/* SILENCE <length> */
      } else if (0 == strcmp ("SILENCE", psz_keyword)) {
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	      if (NULL != cd)
		  cd->tocent[i].silence = cdio_mmssff_to_lba (psz_field);
	  } else {
	      goto format_error;
	  }
	  cdio_log(log_level, "%s line %d: SILENCE not fully implimented",
		   psz_cue_name, i_line);

	/* ZERO <length> */
      } else if (0 == strcmp ("ZERO", psz_keyword)) {
	UNIMPLIMENTED_MSG;

	/* [FILE|AUDIOFILE] "<filename>" <start-msf> [<length-msf>] */
      } else if (0 == strcmp ("FILE", psz_keyword)
		 || 0 == strcmp ("AUDIOFILE", psz_keyword)) {
	if (0 <= i) {
	  if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) {
	    /* Handle "<filename>" */
	    if (cd) {
	      char *psz_dirname = cdio_dirname(psz_cue_name);
	      char *psz_filename = cdio_abspath(psz_dirname, psz_field);
	      cd->tocent[i].filename = strdup (psz_filename);
	      free(psz_filename);
	      free(psz_dirname);
	      /* To do: do something about reusing existing files. */
	      if (!(cd->tocent[i].data_source = cdio_stdio_new (psz_field))) {
		cdio_log (log_level,
			  "%s line %d: can't open file `%s' for reading",
			   psz_cue_name, i_line, psz_field);
		goto err_exit;
	      }
	    } else {
	      CdioDataSource_t *s = cdio_stdio_new (psz_field);
	      if (!s) {
		cdio_log (log_level,
			  "%s line %d: can't open file `%s' for reading",
			  psz_cue_name, i_line, psz_field);
		goto err_exit;
	      }
	      cdio_stdio_destroy (s);
	    }
	  }

	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    /* Handle <start-msf> */
	    lba_t i_start_lba =
	      cdio_lsn_to_lba(cdio_mmssff_to_lba (psz_field));
	    if (CDIO_INVALID_LBA == i_start_lba) {
	      cdio_log(log_level, "%s line %d: invalid MSF string %s",
		       psz_cue_name, i_line, psz_field);
	      goto err_exit;
	    }

	    if (NULL != cd) {
	      cd->tocent[i].start_lba = i_start_lba;
	      cdio_lba_to_msf(i_start_lba, &(cd->tocent[i].start_msf));
	    }
	  }
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    /* Handle <length-msf> */
	    lba_t lba = cdio_mmssff_to_lba (psz_field);
	    if (CDIO_INVALID_LBA == lba) {
	      cdio_log(log_level, "%s line %d: invalid MSF string %s",
		       psz_cue_name, i_line, psz_field);
	      goto err_exit;
	    }
	    if (cd) {
	      off_t i_size = cdio_stream_stat(cd->tocent[i].data_source);
	      if (lba) {
		if ( (lba * cd->tocent[i].datasize) > i_size) {
		  cdio_log(log_level,
			   "%s line %d: MSF length %s exceeds end of file",
			   psz_cue_name, i_line, psz_field);
		  goto err_exit;
		}
	      } else {
		lba = (lba_t) (i_size / cd->tocent[i].blocksize);
	      }
	      cd->tocent[i].sec_count = lba;
	    }
	  }
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    goto format_error;
	  }
	} else {
	  goto not_in_global_section;
	}

	/* DATAFILE "<filename>" #byte-offset <start-msf> */
      } else if (0 == strcmp ("DATAFILE", psz_keyword)) {
	if (0 <= i) {
	  if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) {
	    /* Handle <filename> */
	    char *psz_dirname = cdio_dirname(psz_cue_name);
	    char *psz_filename = cdio_abspath(psz_dirname, psz_field);
	    if (cd) {
	      cd->tocent[i].filename = strdup(psz_filename);
	      /* To do: do something about reusing existing files. */
	      if (!(cd->tocent[i].data_source = cdio_stdio_new (psz_field))) {
		cdio_log (log_level,
			  "%s line %d: can't open file `%s' for reading",
			  psz_cue_name, i_line, psz_field);
		free(psz_filename);
		free(psz_dirname);
		goto err_exit;
	      }
	    } else {
	      CdioDataSource_t *s = cdio_stdio_new (psz_filename);
	      if (!s) {
		cdio_log (log_level,
			  "%s line %d: can't open file `%s' for reading",
			  psz_cue_name, i_line, psz_field);
		free(psz_filename);
		free(psz_dirname);
		goto err_exit;
	      }
	      cdio_stdio_destroy (s);
	    }
	    free(psz_filename);
	    free(psz_dirname);
	  }

	  psz_field = strtok (NULL, " \t\n\r");
	  if (psz_field) {
	    /* Handle optional #byte-offset */
	    if ( psz_field[0] == '#') {
	      long int offset;
	      psz_field++;
	      errno = 0;
	      offset = strtol(psz_field, (char **)NULL, 10);
	      if ( (LONG_MIN == offset || LONG_MAX == offset)
		   && 0 != errno ) {
		cdio_log (log_level,
			  "%s line %d: can't convert `%s' to byte offset",
			  psz_cue_name, i_line, psz_field);
		goto err_exit;
	      } else {
		if (NULL != cd) {
		  cd->tocent[i].offset = offset;
		}
	      }
	      psz_field = strtok (NULL, " \t\n\r");
	    }
	  }
	  if (psz_field) {
	    /* Handle start-msf */
	    lba_t lba = cdio_mmssff_to_lba (psz_field);
	    if (CDIO_INVALID_LBA == lba) {
	      cdio_log(log_level, "%s line %d: invalid MSF string %s",
		       psz_cue_name, i_line, psz_field);
	      goto err_exit;
	    }
	    if (cd) {
	      cd->tocent[i].start_lba = lba;
	      cdio_lba_to_msf(cd->tocent[i].start_lba,
			      &(cd->tocent[i].start_msf));
	    }
	  } else {
	    /* No start-msf. */
	    if (cd) {
	      if (i) {
		uint16_t i_blocksize = cd->tocent[i-1].blocksize;
		off_t i_size      =
		  cdio_stream_stat(cd->tocent[i-1].data_source);

		  check_track_is_blocksize_multiple(cd->tocent[i-1].filename,
						    i-1, i_size, i_blocksize);
		/* Append size of previous datafile. */
		cd->tocent[i].start_lba = (lba_t) (cd->tocent[i-1].start_lba +
		  (i_size / i_blocksize));
	      }
	      cd->tocent[i].offset = 0;
	      cd->tocent[i].start_lba += CDIO_PREGAP_SECTORS;
	      cdio_lba_to_msf(cd->tocent[i].start_lba,
			      &(cd->tocent[i].start_msf));
	    }
	  }

	} else {
	  goto not_in_global_section;
	}

	/* FIFO "<fifo path>" [<length>] */
      } else if (0 == strcmp ("FIFO", psz_keyword)) {
	goto unimplimented_error;

	/* START MM:SS:FF */
      } else if (0 == strcmp ("START", psz_keyword)) {
	if (0 <= i) {
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    /* todo: line is too long! */
	    if (NULL != cd) {
	      cd->tocent[i].pregap = cd->tocent[i].start_lba;
	      cd->tocent[i].start_lba += cdio_mmssff_to_lba (psz_field);
	      cdio_lba_to_msf(cd->tocent[i].start_lba,
			      &(cd->tocent[i].start_msf));
	    }
	  }

	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    goto format_error;
	  }
	} else {
	  goto not_in_global_section;
	}

	/* PREGAP MM:SS:FF */
      } else if (0 == strcmp ("PREGAP", psz_keyword)) {
	if (0 <= i) {
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    if (NULL != cd)
	      cd->tocent[i].pregap = cdio_mmssff_to_lba (psz_field);
	  } else {
	    goto format_error;
	  }
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    goto format_error;
	  }
	} else {
	  goto not_in_global_section;
	}

	  /* INDEX MM:SS:FF */
      } else if (0 == strcmp ("INDEX", psz_keyword)) {
	if (0 <= i) {
	  if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
	    if (NULL != cd) {
#if 0
	      if (1 == cd->tocent[i].nindex) {
		cd->tocent[i].indexes[1] = cd->tocent[i].indexes[0];
		cd->tocent[i].nindex++;
	      }
	      cd->tocent[i].indexes[cd->tocent[i].nindex++] =
		cdio_mmssff_to_lba (psz_field) + cd->tocent[i].indexes[0];
#else
	      ;

#endif
	    }
	  } else {
	    goto format_error;
	  }
	  if (NULL != strtok (NULL, " \t\n\r")) {
	    goto format_error;
	  }
	}  else {
	  goto not_in_global_section;
	}

  /* CD_TEXT { ... } */
  /* todo: opening { must be on same line as CD_TEXT */
      } else if (0 == strcmp ("CD_TEXT", psz_keyword)) {
        if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) {
          goto format_error;
        }
        if ( 0 == strcmp( "{", psz_field ) ) {
          i_cdtext_nest++;
        } else {
          cdio_log (log_level,
              "%s line %d: expecting '{'", psz_cue_name, i_line);
          goto err_exit;
        }

      // TODO: implement language mapping
      } else if (0 == strcmp ("LANGUAGE_MAP", psz_keyword)) {
        /* LANGUAGE d { ... } */
      } else if (0 == strcmp ("LANGUAGE", psz_keyword)) {
        /* Language number */
        if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) {
          goto format_error;
        }
        if ( 0 == strcmp( "{", psz_field ) ) {
          i_cdtext_nest++;
        }
      } else if (0 == strcmp ("{", psz_keyword)) {
        i_cdtext_nest++;
      } else if (0 == strcmp ("}", psz_keyword)) {
        if (i_cdtext_nest > 0) i_cdtext_nest--;
      } else if ( CDTEXT_FIELD_INVALID !=
          (cdtext_key = cdtext_is_field (psz_keyword)) ) {
        if (NULL != cd) {
          if (NULL == cd->gen.cdtext) {
            cd->gen.cdtext = cdtext_init ();
            /* until language mapping is implemented ...*/
            cd->gen.cdtext->block[cd->gen.cdtext->block_i].language_code = CDTEXT_LANGUAGE_ENGLISH;
          }
          cdtext_set (cd->gen.cdtext, cdtext_key, (uint8_t*) strtok (NULL, "\"\t\n\r"),
              (-1 == i ? 0 : cd->gen.i_first_track + i),
              "ISO-8859-1");
        }

	/* unrecognized line */
      } else {
	cdio_log(log_level, "%s line %d: warning: unrecognized word: %s",
		 psz_cue_name, i_line, psz_keyword);
	goto err_exit;
      }
    }
  }

  if (NULL != cd) {
    cd->gen.i_tracks = i+1;
    cd->gen.toc_init = true;
  }

  fclose (fp);
  return true;

 unimplimented_error:
  UNIMPLIMENTED_MSG;
  goto err_exit;

 format_error:
  cdio_log(log_level, "%s line %d after word %s",
	   psz_cue_name, i_line, psz_keyword);
  goto err_exit;

 not_in_global_section:
  cdio_log(log_level, "%s line %d: word %s only allowed in global section",
	   psz_cue_name, i_line, psz_keyword);

 err_exit:
  fclose (fp);
  return false;
}
Exemplo n.º 4
0
/*!
  Open an UDF for reading. Maybe in the future we will have
  a mode. NULL is returned on error.

  Caller must free result - use udf_close for that.
*/
udf_t *
udf_open (const char *psz_path)
{
  udf_t *p_udf = (udf_t *) calloc(1, sizeof(udf_t)) ;
  uint8_t data[UDF_BLOCKSIZE];

  if (!p_udf) return NULL;

  /* Sanity check */
  cdio_assert(sizeof(udf_file_entry_t) == UDF_BLOCKSIZE);

  p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN);
  if (!p_udf->cdio) {
    /* Not a CD-ROM drive or CD Image. Maybe it's a UDF file not
       encapsulated as a CD-ROM Image (e.g. often .UDF or (sic) .ISO)
    */
    p_udf->stream = cdio_stdio_new( psz_path );
    if (!p_udf->stream)
      goto error;
    p_udf->b_stream = true;
  }

  /*
   * Look for an Anchor Volume Descriptor Pointer at sector 256.
   */
  if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, &data, 256, 1) )
    goto error;

  memcpy(&(p_udf->anchor_vol_desc_ptr), &data, sizeof(anchor_vol_desc_ptr_t));

  if (udf_checktag((udf_tag_t *)&(p_udf->anchor_vol_desc_ptr), TAGID_ANCHOR))
    goto error;

  /*
   * Then try to find a reference to a Primary Volume Descriptor.
   */
  {
    anchor_vol_desc_ptr_t *p_avdp = &p_udf->anchor_vol_desc_ptr;

    const uint32_t mvds_start =
      uint32_from_le(p_avdp->main_vol_desc_seq_ext.loc);
    const uint32_t mvds_end   = mvds_start +
      (uint32_from_le(p_avdp->main_vol_desc_seq_ext.len) - 1) / UDF_BLOCKSIZE;

    uint32_t i_lba;

    for (i_lba = mvds_start; i_lba < mvds_end; i_lba++) {
      udf_pvd_t *p_pvd = (udf_pvd_t *) &data;

      if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_pvd, i_lba, 1) )
	goto error;

      if (!udf_checktag(&p_pvd->tag, TAGID_PRI_VOL)) {
	p_udf->pvd_lba = i_lba;
	break;
      }

    }

    /*
     * If we couldn't find a reference, bail out.
     */
    if (i_lba == mvds_end)
      goto error;
  }

  return p_udf;

 error:
  cdio_stdio_destroy(p_udf->stream);
  free(p_udf);
  return NULL;
}