/*! Close previously opened ISO 9660 image. True is unconditionally returned. If there was an error false would be returned. */ bool iso9660_close (iso9660_t *p_iso) { if (NULL != p_iso) { cdio_stdio_destroy(p_iso->stream); free(p_iso); } return true; }
/*! Release and free resources associated with stream or disk image. */ void cdio_generic_stdio_free (void *p_user_data) { generic_img_private_t *p_env = p_user_data; if (NULL == p_env) return; if (NULL != p_env->source_name) free (p_env->source_name); if (p_env->data_source) cdio_stdio_destroy (p_env->data_source); }
/*! Close UDF and free resources associated with p_udf. */ bool udf_close (udf_t *p_udf) { if (!p_udf) return true; if (p_udf->b_stream) { cdio_stdio_destroy(p_udf->stream); } else { cdio_destroy(p_udf->cdio); } /* Get rid of root directory if allocated. */ free_and_null(p_udf); return true; }
/*! 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; }
/*! We don't need the image any more. Free all memory associated with it. */ void _free_image (void *p_user_data) { _img_private_t *p_env = p_user_data; track_t i_track; if (NULL == p_env) return; for (i_track=0; i_track < p_env->gen.i_tracks; i_track++) { track_info_t *p_tocent = &(p_env->tocent[i_track]); free_if_notnull(p_tocent->filename); free_if_notnull(p_tocent->isrc); cdtext_destroy(&(p_tocent->cdtext)); if (p_tocent->data_source) cdio_stdio_destroy(p_tocent->data_source); } free_if_notnull(p_env->psz_mcn); free_if_notnull(p_env->psz_cue_name); free_if_notnull(p_env->psz_access_mode); cdtext_destroy(&(p_env->gen.cdtext)); cdio_generic_stdio_free(p_env); free(p_env); }
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; }
/*! 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; }