/* 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; }
/*! Reads a single mode1 form1 or form2 sector from cd device into data starting from lsn. Returns 0 if no error. */ int cdio_read_mode1_sector (const CdIo *cdio, void *data, lsn_t lsn, bool is_form2) { uint32_t size = is_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; char buf[M2RAW_SECTOR_SIZE] = { 0, }; int ret; cdio_assert (cdio != NULL); cdio_assert (data != NULL); if (cdio->op.lseek && cdio->op.read) { if (0 > cdio_lseek(cdio, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) return -1; if (0 > cdio_read(cdio, buf, CDIO_CD_FRAMESIZE)) return -1; memcpy (data, buf, size); return 0; } else { ret = cdio_read_mode2_sector(cdio, data, lsn, is_form2); if (ret == 0) memcpy (data, buf+CDIO_CD_SUBHEADER_SIZE, size); } return ret; }
static void _fs_stat_root (const CdIo *cdio, iso9660_stat_t *stat, bool is_mode2) { char block[ISO_BLOCKSIZE] = { 0, }; const iso9660_pvd_t *pvd = (void *) █ const iso9660_dir_t *idr = (void *) pvd->root_directory_record; if (is_mode2) { if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } _idr2statbuf (idr, stat, is_mode2); }
/**************************************************************************** * ioctl_ReadSector: Read a sector (2324 bytes) ****************************************************************************/ int ioctl_ReadSector( vlc_object_t *p_this, const cddev_t *p_cddev, int i_sector, byte_t * p_buffer ) { typedef struct { uint8_t subheader [8]; uint8_t data [M2F2_SECTOR_SIZE]; } vcdsector_t; vcdsector_t vcd_sector; if( cdio_read_mode2_sector(p_cddev->cdio, &vcd_sector, i_sector, VLC_TRUE) != 0) { // msg_Err( p_this, "Could not read sector %d", i_sector ); return -1; } memcpy (p_buffer, vcd_sector.data, M2F2_SECTOR_SIZE); return( 0 ); }
/*! Read the Primary Volume Descriptor for of CD. */ bool iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd) { /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ bool b_mode2; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; int i_rc; switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } i_rc = b_mode2 ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR, false); if (i_rc) { cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); return false; } /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); return check_pvd(p_pvd); }
static int read_sector(bgav_input_context_t * ctx, uint8_t * data) { vcd_priv * priv; priv = ctx->priv; // do // { if(priv->next_sector > priv->tracks[priv->current_track].end_sector) return 0; if(cdio_read_mode2_sector(priv->cdio, data, priv->next_sector, true)!=0) { return 0; } priv->next_sector++; priv->last_sector = priv->next_sector - 1; #ifndef SECTOR_ACCESS priv->buffer_ptr = priv->buffer; #endif // gavl_hexdump(priv->buffer_ptr, 32, 16); return 1; }
/*! Read block into p_buf and return the status back. This routine is a bit complicated because on reaching the end of a track or entry we may automatically advance to the item, or interpret the next item in the playback-control list. */ vcdplayer_read_status_t vcdplayer_read (access_t * p_access, uint8_t *p_buf) { /* p_access->handle_events (); */ uint8_t wait_time=0; vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; if ( p_vcdplayer->i_lsn > p_vcdplayer->end_lsn ) { vcdplayer_read_status_t read_status; /* We've run off of the end of this entry. Do we continue or stop? */ dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "end reached, cur: %u, end: %u\n", p_vcdplayer->i_lsn, p_vcdplayer->end_lsn); handle_item_continuation: read_status = vcdplayer_pbc_is_on( p_vcdplayer ) ? vcdplayer_pbc_nav( p_access, &wait_time ) : vcdplayer_non_pbc_nav( p_access, &wait_time ); if (READ_STILL_FRAME == read_status) { *p_buf = wait_time; return READ_STILL_FRAME; } if (READ_BLOCK != read_status) return read_status; } /* Read the next block. Important note: we probably speed things up by removing "data" and the memcpy to it by extending vcd_image_source_read_mode2 to allow a mode to do what's below in addition to its "raw" and "block" mode. It also would probably improve the modularity a little bit as well. */ { CdIo *p_img = vcdinfo_get_cd_image(p_vcdplayer->vcd); typedef struct { uint8_t subheader [CDIO_CD_SUBHEADER_SIZE]; uint8_t data [M2F2_SECTOR_SIZE]; uint8_t spare [4]; } vcdsector_t; vcdsector_t vcd_sector; do { if (cdio_read_mode2_sector(p_img, &vcd_sector, p_vcdplayer->i_lsn, true)!=0) { dbg_print(INPUT_DBG_LSN, "read error\n"); p_vcdplayer->i_lsn++; return READ_ERROR; } p_vcdplayer->i_lsn++; if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) { /* We've run off of the end of this entry. Do we continue or stop? */ dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "end reached in reading, cur: %u, end: %u\n", p_vcdplayer->i_lsn, p_vcdplayer->end_lsn); break; } /* Check header ID for a padding sector and simply discard these. It is alleged that VCD's put these in to keep the bitrate constant. */ } while((vcd_sector.subheader[2]&~0x01)==0x60); if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) /* We've run off of the end of this entry. Do we continue or stop? */ goto handle_item_continuation; memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE); return READ_BLOCK; } }
/*! Read the Super block of an ISO 9660 image. This is the Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume Descriptor if (Joliet) extensions are acceptable. */ bool iso9660_fs_read_superblock (CdIo_t *p_cdio, iso_extension_mask_t iso_extension_mask) { if (!p_cdio) return false; { generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; iso9660_pvd_t *p_pvd = &(p_env->pvd); iso9660_svd_t *p_svd = &(p_env->svd); char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; bool b_mode2; int i_rc; /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) ) return false; p_env->i_joliet_level = 0; i_rc = (b_mode2) ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false); if (0 == i_rc) { /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t)); memcpy(p_svd, buf, sizeof(iso9660_svd_t)); if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { if (p_svd->escape_sequences[0] == 0x25 && p_svd->escape_sequences[1] == 0x2f) { switch (p_svd->escape_sequences[2]) { case 0x40: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) p_env->i_joliet_level = 1; break; case 0x43: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) p_env->i_joliet_level = 2; break; case 0x45: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) p_env->i_joliet_level = 3; break; default: cdio_info("Supplementary Volume Descriptor found, but not Joliet"); } if (p_env->i_joliet_level > 0) { cdio_info("Found Extension: Joliet Level %d", p_env->i_joliet_level); } } } } } return true; }