diff --git a/configure.ac b/configure.ac index 2421ebae..2cabf3b1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_REVISION([$Id: configure.ac,v 1.1 2003/03/24 19:01:09 rocky Exp $])dnl +AC_REVISION([$Id: configure.ac,v 1.2 2003/03/29 17:32:00 rocky Exp $])dnl AC_INIT(lib/cdio.c) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE(libcdio, 0.1) @@ -118,7 +118,8 @@ LIBS="$LIBS -lm" CFLAGS="$CFLAGS $WARN_CFLAGS" AM_CONDITIONAL(CYGWIN, test "x$CYGWIN" = "xyes") -AM_CONDITIONAL(BUILD_CDINFO_LINUX, test "x$enable_cli_fe" = "xyes") +AM_CONDITIONAL(BUILD_CDINFO_LINUX, test "x$enable_cdinfo_linux" = "xyes") +AM_CONDITIONAL(BUILD_CDIOTEST, test "x$enable_cdiotest" = "xyes") AM_PROG_LIBTOOL diff --git a/lib/Makefile.am b/lib/Makefile.am index 93d8b4b6..42d2c4fd 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.2 2003/03/24 23:59:22 rocky Exp $ +# $Id: Makefile.am,v 1.3 2003/03/29 17:32:00 rocky Exp $ # # Copyright (C) 2003 Rocky Bernstein # @@ -29,6 +29,7 @@ libcdio_sources = \ _cdio_bincue.c \ _cdio_bsdi.c \ _cdio_freebsd.c \ + _cdio_generic.c \ _cdio_linux.c \ _cdio_nrg.c \ _cdio_stdio.c \ diff --git a/lib/_cdio_bincue.c b/lib/_cdio_bincue.c index c98e4629..2a4814d3 100644 --- a/lib/_cdio_bincue.c +++ b/lib/_cdio_bincue.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_bincue.c,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_bincue.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002,2003 Rocky Bernstein @@ -28,7 +28,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_bincue.c,v 1.1 2003/03/24 19:01:09 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_bincue.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; #include #include @@ -49,9 +49,12 @@ static const char _rcsid[] = "$Id: _cdio_bincue.c,v 1.1 2003/03/24 19:01:09 rock typedef struct { int blocksize; - int track_num; /* Probably is index+1 */ + int track_num; /* Probably is index+1 */ msf_t start_msf; + lba_t start_lba; int start_index; + int sec_count; /* Number of sectors in this track. Does not + include pregap */ int num_indices; int flags; /* "DCP", "4CH", "PRE" */ track_format_t track_format; @@ -61,16 +64,16 @@ typedef struct { typedef struct { + char *source_name; + bool init; bool sector_2336_flag; - CdioDataSource *bin_src; - char *source_name; + CdioDataSource *data_source; char *cue_name; track_info_t tocent[100]; /* entry info for each track */ track_t total_tracks; /* number of tracks in image */ track_t first_track_num; /* track number of first track */ bool have_cue; - bool init; } _img_private_t; static bool _cdio_image_read_cue (_img_private_t *_obj); @@ -82,36 +85,12 @@ static uint32_t _cdio_stat_size (void *user_data); static bool _cdio_init (_img_private_t *_obj) { + lsn_t lead_lsn; + if (_obj->init) return false; - /* Read in CUE sheet. */ - if ((_obj->cue_name != NULL)) { - _obj->have_cue == _cdio_image_read_cue(_obj); - } - - if (!_obj->have_cue ) { - /* Time to fake things... - Make one big track, track 0 and 1 are the same. - We are guessing stuff atarts a msf 00:04:00 - 2 for the 150 - sector pregap and 2 for the cue information. - */ - int blocksize = _obj->sector_2336_flag - ? M2RAW_SECTOR_SIZE : CD_RAW_SECTOR_SIZE; - _obj->total_tracks = 2; - _obj->first_track_num = 1; - _obj->tocent[0].start_msf.m = to_bcd8(0); - _obj->tocent[0].start_msf.s = to_bcd8(4); - _obj->tocent[0].start_msf.f = to_bcd8(0); - _obj->tocent[0].blocksize = blocksize; - _obj->tocent[0].track_format= TRACK_FORMAT_XA; - _obj->tocent[0].track_green = true; - - _obj->tocent[1] = _obj->tocent[0]; - } - - - if (!(_obj->bin_src = cdio_stdio_new (_obj->source_name))) { + if (!(_obj->data_source = cdio_stdio_new (_obj->source_name))) { cdio_error ("init failed"); return false; } @@ -121,12 +100,113 @@ _cdio_init (_img_private_t *_obj) */ _obj->init = true; - /* Fake out leadout track. */ - cdio_lsn_to_msf ( _cdio_stat_size( (_img_private_t *) _obj), - &_obj->tocent[_obj->total_tracks].start_msf); + lead_lsn = _cdio_stat_size( (_img_private_t *) _obj); + + /* Read in CUE sheet. */ + if ((_obj->cue_name != NULL)) { + _obj->have_cue == _cdio_image_read_cue(_obj); + } + + if (!_obj->have_cue ) { + /* Time to fake things... + Make one big track, track 0 and 1 are the same. + We are guessing stuff starts at msf 00:04:00 - 2 for the 150 + sector pregap and 2 for the cue information. + */ + track_info_t *this_track=&(_obj->tocent[0]); + int blocksize = _obj->sector_2336_flag + ? M2RAW_SECTOR_SIZE : CD_RAW_SECTOR_SIZE; + + _obj->total_tracks = 2; + _obj->first_track_num = 1; + this_track->start_msf.m = to_bcd8(0); + this_track->start_msf.s = to_bcd8(4); + this_track->start_msf.f = to_bcd8(0); + this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); + this_track->blocksize = blocksize; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + + + _obj->tocent[1] = _obj->tocent[0]; + } + + /* Fake out leadout track and sector count for last track*/ + cdio_lsn_to_msf (lead_lsn, &_obj->tocent[_obj->total_tracks].start_msf); + _obj->tocent[_obj->total_tracks].start_lba = cdio_lsn_to_lba(lead_lsn); + _obj->tocent[_obj->total_tracks-1].sec_count = + cdio_lsn_to_lba(lead_lsn - _obj->tocent[_obj->total_tracks-1].start_lba); return true; +} +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Would be libc's seek() but we have to adjust for the extra track header + information in each sector. +*/ +static off_t +_cdio_lseek (void *user_data, off_t offset, int whence) +{ + _img_private_t *_obj = user_data; + + /* real_offset is the real byte offset inside the disk image + The number below was determined empirically. I'm guessing + the 1st 24 bytes of a bin file are used for something. + */ + off_t real_offset=24; + + unsigned int i; + unsigned int user_datasize; + + for (i=0; i<_obj->total_tracks; i++) { + track_info_t *this_track=&(_obj->tocent[i]); + switch (this_track->track_format) { + case TRACK_FORMAT_AUDIO: + user_datasize=CDDA_SECTOR_SIZE; + break; + case TRACK_FORMAT_CDI: + user_datasize=FORM1_DATA_SIZE; + break; + case TRACK_FORMAT_XA: + user_datasize=FORM1_DATA_SIZE; + break; + default: + cdio_warn ("track %d has unknown format %d", + i+1, this_track->track_format); + } + + if ( (this_track->sec_count*user_datasize) >= offset) { + int blocks = offset / user_datasize; + int rem = offset % user_datasize; + int block_offset = blocks * CD_RAW_SECTOR_SIZE; + real_offset += block_offset + rem; + break; + } + real_offset += this_track->sec_count*CD_RAW_SECTOR_SIZE; + offset -= this_track->sec_count*user_datasize; + } + + if (i==_obj->total_tracks) { + cdio_warn ("seeking outside range of disk image"); + return -1; + } else + return cdio_stream_seek(_obj->data_source, real_offset, whence); +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + FIXME: + At present we assume a read doesn't cross sector or track + boundaries. +*/ +static ssize_t +_cdio_read (void *user_data, void *buf, size_t size) +{ + _img_private_t *_obj = user_data; + return cdio_stream_read(_obj->data_source, buf, size, 1); } /*! @@ -142,7 +222,7 @@ _cdio_stat_size (void *user_data) _cdio_init (_obj); - size = cdio_stream_stat (_obj->bin_src); + size = cdio_stream_stat (_obj->data_source); if (size % blocksize) { @@ -194,48 +274,79 @@ _cdio_image_read_cue (_img_private_t *_obj) */ /* printf("Found file name %s\n", s); */ } else if (2==sscanf(p, "TRACK %d MODE2/%d", &track_num, &blocksize)) { - _obj->tocent[_obj->total_tracks].blocksize = blocksize; - _obj->tocent[_obj->total_tracks].track_num = track_num; - _obj->tocent[_obj->total_tracks].num_indices = 0; - _obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_XA; - _obj->tocent[_obj->total_tracks].track_green = true; + track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); + this_track->blocksize = blocksize; + this_track->track_num = track_num; + this_track->num_indices = 0; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; _obj->total_tracks++; seen_first_index_for_track=false; /*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/ } else if (2==sscanf(p, "TRACK %d MODE1/%d", &track_num, &blocksize)) { - _obj->tocent[_obj->total_tracks].blocksize = blocksize; - _obj->tocent[_obj->total_tracks].track_num = track_num; - _obj->tocent[_obj->total_tracks].num_indices = 0; - _obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_CDI; - _obj->tocent[_obj->total_tracks].track_green = false; + track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); + this_track->blocksize = blocksize; + this_track->track_num = track_num; + this_track->num_indices = 0; + this_track->track_format= TRACK_FORMAT_CDI; + this_track->track_green = false; _obj->total_tracks++; seen_first_index_for_track=false; /*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/ } else if (1==sscanf(p, "TRACK %d AUDIO", &track_num)) { - _obj->tocent[_obj->total_tracks].blocksize = blocksize; - _obj->tocent[_obj->total_tracks].track_num = track_num; - _obj->tocent[_obj->total_tracks].num_indices = 0; - _obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_AUDIO; - _obj->tocent[_obj->total_tracks].track_green = false; + track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); + this_track->blocksize = CDDA_SECTOR_SIZE; + this_track->track_num = track_num; + this_track->num_indices = 0; + this_track->track_format= TRACK_FORMAT_AUDIO; + this_track->track_green = false; _obj->total_tracks++; seen_first_index_for_track=false; } else if (4==sscanf(p, "INDEX %d %d:%d:%d", &start_index, &min, &sec, &frame)) { + track_info_t *this_track=&(_obj->tocent[_obj->total_tracks-1]); /* FIXME! all of this is a big hack. If start_index == 0, then this is the "last_cue" information. The +2 below seconds is to adjust for the 150 pregap. */ - if (!seen_first_index_for_track && start_index != 0) { - _obj->tocent[_obj->total_tracks-1].start_index = start_index; - _obj->tocent[_obj->total_tracks-1].start_msf.m = to_bcd8 (min); - _obj->tocent[_obj->total_tracks-1].start_msf.s = to_bcd8 (sec)+2; - _obj->tocent[_obj->total_tracks-1].start_msf.f = to_bcd8 (frame); - seen_first_index_for_track=true; + if (start_index != 0) { + if (!seen_first_index_for_track) { + this_track->start_index = start_index; + this_track->start_msf.m = to_bcd8 (min); + this_track->start_msf.s = to_bcd8 (sec)+2; + this_track->start_msf.f = to_bcd8 (frame); + this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); + seen_first_index_for_track=true; + } + + if (_obj->total_tracks > 1) { + /* Figure out number of sectors for previous track */ + track_info_t *prev_track=&(_obj->tocent[_obj->total_tracks-2]); + if ( this_track->start_lba < prev_track->start_lba ) { + cdio_warn ("track %d at LBA %d starts before track %d at LBA %d", + _obj->total_tracks, this_track->start_lba, + _obj->total_tracks-1, prev_track->start_lba); + prev_track->sec_count = 0; + } else if ( this_track->start_lba >= prev_track->start_lba + + CDIO_PREGAP_SECTORS ) { + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba - CDIO_PREGAP_SECTORS ; + } else { + cdio_warn ("%d fewer than pregap (%d) sectors in track %d", + this_track->start_lba - prev_track->start_lba, + CDIO_PREGAP_SECTORS, + _obj->total_tracks-1); + /* Include pregap portion in sec_count. Maybe the pregap + was omitted. */ + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba; + } + } + this_track->num_indices++; } - _obj->tocent[_obj->total_tracks-1].num_indices++; } } _obj->have_cue = _obj->total_tracks != 0; @@ -254,8 +365,8 @@ _cdio_free (void *user_data) free (_obj->source_name); - if (_obj->bin_src) - cdio_stream_destroy (_obj->bin_src); + if (_obj->data_source) + cdio_stream_destroy (_obj->data_source); free (_obj); } @@ -271,16 +382,16 @@ _read_mode2_sector (void *user_data, void *data, uint32_t lsn, _cdio_init (_obj); - cdio_stream_seek (_obj->bin_src, lsn * blocksize); + cdio_stream_seek (_obj->data_source, lsn * blocksize, SEEK_SET); - cdio_stream_read (_obj->bin_src, + cdio_stream_read (_obj->data_source, _obj->sector_2336_flag ? (buf + 12 + 4) : buf, blocksize, 1); if (mode2_form2) memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE); else - memcpy (data, buf + 12 + 4 + 8, M2F1_SECTOR_SIZE); + memcpy (data, buf + 12 + 4 + 8, FORM1_DATA_SIZE); return 0; } @@ -310,7 +421,7 @@ _read_mode2_sectors (void *user_data, void *data, uint32_t lsn, return retval; memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8, - M2F1_SECTOR_SIZE); + FORM1_DATA_SIZE); } } return 0; @@ -459,11 +570,33 @@ _cdio_get_track_green(void *user_data, track_t track_num) return _obj->tocent[track_num-1].track_green; } +/*! + Return the starting MSF (minutes/secs/frames) for track number + track_num in obj. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + 1 is returned on error. +*/ +static lba_t +_cdio_get_track_lba(void *user_data, track_t track_num) +{ + _img_private_t *_obj = user_data; + _cdio_init (_obj); + + if (track_num == CDIO_LEADOUT_TRACK) track_num = _obj->total_tracks+1; + + if (track_num <= _obj->total_tracks+1 && track_num != 0) { + return _obj->tocent[track_num-1].start_lba; + } else + return CDIO_INVALID_LBA; +} + /*! Return the starting MSF (minutes/secs/frames) for the track number track_num in obj. Tracks numbers start at 1. - Since there are no tracks, unless the track number is is 1 we return - falure. If the track number is 1, we return 00:00:00. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + */ static bool _cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf) @@ -497,7 +630,7 @@ cdio_open_bincue (const char *source_name) .get_num_tracks = _cdio_get_num_tracks, .get_track_format = _cdio_get_track_format, .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* This could be implemented if need be. */ + .get_track_lba = _cdio_get_track_lba, .get_track_msf = _cdio_get_track_msf, .read_mode2_sector = _read_mode2_sector, .read_mode2_sectors = _read_mode2_sectors, @@ -535,8 +668,10 @@ cdio_open_cue (const char *cue_name) .get_num_tracks = _cdio_get_num_tracks, .get_track_format = _cdio_get_track_format, .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* This could be implemented if need be. */ + .get_track_lba = _cdio_get_track_lba, .get_track_msf = _cdio_get_track_msf, + .lseek = _cdio_lseek, + .read = _cdio_read, .read_mode2_sector = _read_mode2_sector, .read_mode2_sectors = _read_mode2_sectors, .set_arg = _cdio_set_arg, diff --git a/lib/_cdio_bsdi.c b/lib/_cdio_bsdi.c index 79a45039..110ce66d 100644 --- a/lib/_cdio_bsdi.c +++ b/lib/_cdio_bsdi.c @@ -1,8 +1,8 @@ /* - $Id: _cdio_bsdi.c,v 1.2 2003/03/24 23:59:22 rocky Exp $ + $Id: _cdio_bsdi.c,v 1.3 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel - Copyright (C) 2003 Rocky Bernstein + Copyright (C) 2002,2003 Rocky Bernstein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,85 +18,74 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* This file contains Linux-specific code and implements low-level + control of the CD drive. +*/ #ifdef HAVE_CONFIG_H # include "config.h" #endif +static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.3 2003/03/29 17:32:00 rocky Exp $"; + #include "cdio_assert.h" #include "cdio_private.h" -#include "util.h" #include "sector.h" -#include "logging.h" +#include "util.h" + +#ifdef HAVE_BSDI_CDROM #include #include #include - -static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2003/03/24 23:59:22 rocky Exp $"; - -#if HAVE_BSDI_CDROM - -#include -#include - -#include -#include -#include - #include -#include #include +#include -/* reader */ +#include +#include +#include +#include + +#define DEFAULT_CDIO_DEVICE "/dev/sr0" + +#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1) +#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) typedef struct { int fd; + int ioctls_debugged; /* for debugging */ + enum { _AM_NONE, - _AM_READ_CD, - _AM_READ_10 + _AM_IOCTL, } access_mode; char *source_name; bool init; + + /* Track information */ + bool toc_init; /* if true, info below is valid. */ + struct cdrom_tochdr tochdr; + struct cdrom_tocentry tocent[100]; /* entry info for each track */ + } _img_private_t; -static int -_scsi_cmd (int fd, struct scsi_user_cdb *sucp, const char *tag) -{ - u_char *cp; - - if (ioctl (fd, SCSIRAWCDB, sucp)) - { - vcd_error ("%s: ioctl (SCSIRAWCDB): %s", tag, strerror (errno)); - return 1; - } - if (sucp->suc_sus.sus_status) - { - cp = sucp->suc_sus.sus_sense; - vcd_info("%s: cmd: %x sus_status %d ", tag, sucp->suc_cdb[0], - sucp->suc_sus.sus_status); - vcd_info(" sense: %x %x %x %x %x %x %x %x", cp[0], cp[1], cp[2], - cp[3], cp[4], cp[5], cp[6], cp[7]); - return 1; - } - return 0; -} - /*! Initialize CD device. */ static bool _cdio_init (_img_private_t *_obj) { - if (_obj->init) - return; - + if (_obj->init) { + cdio_error ("init called more than once"); + return false; + } + _obj->fd = open (_obj->source_name, O_RDONLY, 0); - _obj->access_mode = _AM_READ_CD; if (_obj->fd < 0) { @@ -109,7 +98,6 @@ _cdio_init (_img_private_t *_obj) return true; } - /*! Release and free resources associated with cd. */ @@ -118,240 +106,128 @@ _cdio_free (void *user_data) { _img_private_t *_obj = user_data; + if (NULL == _obj) return; free (_obj->source_name); - if (_obj->fd) + if (_obj->fd >= 0) close (_obj->fd); free (_obj); } -static int -_set_bsize (int fd, unsigned int bsize) -{ - struct - { - uint8_t reserved1; - uint8_t medium; - uint8_t reserved2; - uint8_t block_desc_length; - uint8_t density; - uint8_t number_of_blocks_hi; - uint8_t number_of_blocks_med; - uint8_t number_of_blocks_lo; - uint8_t reserved3; - uint8_t block_length_hi; - uint8_t block_length_med; - uint8_t block_length_lo; - } mh; - - struct scsi_user_cdb suc; - - memset (&mh, 0, sizeof (mh)); - memset (&suc, 0, sizeof (struct scsi_user_cdb)); - - suc.suc_cdb[0] = 0x15; - suc.suc_cdb[1] = 1 << 4; - suc.suc_cdb[4] = 12; - suc.suc_cdblen = 6;; - - suc.suc_data = (u_char *)&mh; - suc.suc_datalen = sizeof (mh); - - suc.suc_timeout = 500; - suc.suc_flags = SUC_WRITE; - - mh.block_desc_length = 0x08; - mh.block_length_hi = (bsize >> 16) & 0xff; - mh.block_length_med = (bsize >> 8) & 0xff; - mh.block_length_lo = (bsize >> 0) & 0xff; - - return _scsi_cmd (fd, &suc, "_set_bsize"); -} - +/*! + Reads a single mode2 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ static int -_read_mode2 (int fd, void *buf, uint32_t lba, unsigned nblocks, - bool _workaround) +_read_mode2_sector (void *user_data, void *data, lsn_t lsn, + bool mode2_form2) { - struct scsi_user_cdb suc; - int retval = 0; + char buf[M2RAW_SECTOR_SIZE] = { 0, }; + struct cdrom_msf *msf = (struct cdrom_msf *) &buf; + msf_t _msf; - memset (&suc, 0, sizeof (struct scsi_user_cdb)); - - suc.suc_cdb[0] = (_workaround - ? 0x28 /* CMD_READ_10 */ - : 0xbe /* CMD_READ_CD */); - - if (!_workaround) - suc.suc_cdb[1] = 0; /* sector size mode2 */ - - suc.suc_cdb[2] = (lba >> 24) & 0xff; - suc.suc_cdb[3] = (lba >> 16) & 0xff; - suc.suc_cdb[4] = (lba >> 8) & 0xff; - suc.suc_cdb[5] = (lba >> 0) & 0xff; - - suc.suc_cdb[6] = (nblocks >> 16) & 0xff; - suc.suc_cdb[7] = (nblocks >> 8) & 0xff; - suc.suc_cdb[8] = (nblocks >> 0) & 0xff; - - if (!_workaround) - suc.suc_cdb[9] = 0x58; /* 2336 mode2 mixed form */ - - suc.suc_cdblen = _workaround ? 10 : 12; - - suc.suc_data = buf; - suc.suc_datalen = 2336 * nblocks; - - suc.suc_timeout = 500; - suc.suc_flags = SUC_READ; - - if (_workaround) - { - if ((retval = _set_bsize (fd, 2336))) - goto out; - - if ((retval = _scsi_cmd(fd, &suc, "_read_mode2_workaround"))) - { - _set_bsize (fd, 2048); - goto out; - } - retval = _set_bsize (fd, 2048); - } - else - retval = _scsi_cmd(fd, &suc, "_read_mode2"); - - out: - return retval; -} - -static int -_read_mode2_sector (void *user_data, void *data, uint32_t lsn, bool form2) -{ _img_private_t *_obj = user_data; - _cdio_init (_obj); + cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); + msf->cdmsf_min0 = from_bcd8(_msf.m); + msf->cdmsf_sec0 = from_bcd8(_msf.s); + msf->cdmsf_frame0 = from_bcd8(_msf.f); - if (form2) + if (_obj->ioctls_debugged == 75) + cdio_debug ("only displaying every 75th ioctl from now on"); + + if (_obj->ioctls_debugged == 30 * 75) + cdio_debug ("only displaying every 30*75th ioctl from now on"); + + if (_obj->ioctls_debugged < 75 + || (_obj->ioctls_debugged < (30 * 75) + && _obj->ioctls_debugged % 75 == 0) + || _obj->ioctls_debugged % (30 * 75) == 0) + cdio_debug ("reading %2.2d:%2.2d:%2.2d", + msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); + + _obj->ioctls_debugged++; + + switch (_obj->access_mode) { - retry: - switch (_obj->access_mode) + case _AM_NONE: + cdio_error ("no way to read mode2"); + return 1; + break; + + case _AM_IOCTL: + if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1) { - case _AM_NONE: - vcd_error ("no way to read mode2"); + perror ("ioctl()"); return 1; - break; - - case _AM_READ_CD: - case _AM_READ_10: - if (_read_mode2 (_obj->fd, data, lsn, 1, - (_obj->access_mode == _AM_READ_10))) - { - if (_obj->access_mode == _AM_READ_CD) - { - vcd_info ("READ_CD failed; switching to READ_10 mode..."); - _obj->access_mode = _AM_READ_10; - goto retry; - } - else - { - vcd_info ("READ_10 failed; no way to read mode2 left."); - _obj->access_mode = _AM_NONE; - goto retry; - } - return 1; - } - break; + /* exit (EXIT_FAILURE); */ } + break; + } + + if (mode2_form2) + memcpy (data, buf, M2RAW_SECTOR_SIZE); else - { - char buf[M2RAW_SIZE] = { 0, }; - int retval; - - if ((retval = _read_mode2_sector (_obj, buf, lsn, true))) - return retval; - - memcpy (data, buf + 8, M2F1_SECTOR_SIZE); - } - + memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE); + return 0; } -static const u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; +/*! + Reads nblocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ +static int +_read_mode2_sectors (void *user_data, void *data, lsn_t lsn, + bool mode2_form2, unsigned nblocks) +{ + _img_private_t *_obj = user_data; + int i; + int retval; + for (i = 0; i < nblocks; i++) { + if (mode2_form2) { + if ( (retval = _read_mode2_sector (_obj, + ((char *)data) + (M2RAW_SECTOR_SIZE * i), + lsn + i, true)) ) + return retval; + } else { + char buf[M2RAW_SECTOR_SIZE] = { 0, }; + if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) ) + return retval; + + memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8, + FORM1_DATA_SIZE); + } + } + return 0; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + */ static uint32_t _cdio_stat_size (void *user_data) { _img_private_t *_obj = user_data; - struct scsi_user_cdb suc; - uint8_t buf[12] = { 0, }; + struct cdrom_tocentry tocent; + uint32_t size; - uint32_t retval; - - _cdio_init(_obj); - - memset (&suc, 0, sizeof (struct scsi_user_cdb)); - - suc.suc_cdb[0] = 0x43; /* CMD_READ_TOC_PMA_ATIP */ - suc.suc_cdb[1] = 0; /* lba; msf: 0x2 */ - suc.suc_cdb[6] = 0xaa; /* CDROM_LEADOUT */ - suc.suc_cdb[8] = 12; /* ? */ - suc.suc_cdblen = 10; - - suc.suc_data = buf; - suc.suc_datalen = sizeof (buf); - - suc.suc_timeout = 500; - suc.suc_flags = SUC_READ; - - if (_scsi_cmd(_obj->fd, &suc, "_cdio_stat_size")) - return 0; - - { - int i; - - retval = 0; - for (i = 8; i < 12; i++) - { - retval <<= 8; - retval += buf[i]; - } - } - - return retval; -} - -/*! - Return the value associated with the key "arg". -*/ -static const char * -_cdio_get_arg (void *user_data, const char key[]) -{ - _img_private_t *_obj = user_data; - - if (!strcmp (key, "source")) { - return _obj->source_name; - } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { - case _AM_READ_CD: - return "READ_CD"; - case _AM_READ_10: - return "READ_10"; - case _AM_NONE: - return "no access method"; + tocent.cdte_track = CDROM_LEADOUT; + tocent.cdte_format = CDROM_LBA; + if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1) + { + perror ("ioctl(CDROMREADTOCENTRY)"); + exit (EXIT_FAILURE); } - } - return NULL; -} -/*! - Return a string containing the default VCD device if none is specified. - */ -static char * -_cdio_get_default_device() -{ - return strdup(DEFAULT_CDIO_DEVICE); + size = tocent.cdte_addr.lba; + + return size; } /*! @@ -373,10 +249,8 @@ _cdio_set_arg (void *user_data, const char key[], const char value[]) } else if (!strcmp (key, "access-mode")) { - if (!strcmp(value, "READ_CD")) - _obj->access_mode = _AM_READ_CD; - else if (!strcmp(value, "READ_10")) - _obj->access_mode = _AM_READ_10; + if (!strcmp(value, "IOCTL")) + _obj->access_mode = _AM_IOCTL; else cdio_error ("unknown access type: %s. ignored.", value); } @@ -386,13 +260,254 @@ _cdio_set_arg (void *user_data, const char key[], const char value[]) return 0; } +/*! + Read and cache the CD's Track Table of Contents and track info. + Return false if successful or true if an error. +*/ +static bool +_cdio_read_toc (_img_private_t *_obj) +{ + int i; + + /* read TOC header */ + if ( ioctl(_obj->fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { + cdio_error("%s: %s\n", + "error in ioctl CDROMREADTOCHDR", strerror(errno)); + return false; + } + + /* read individual tracks */ + for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) { + _obj->tocent[i-1].cdte_track = i; + _obj->tocent[i-1].cdte_format = CDROM_MSF; + if ( ioctl(_obj->fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { + cdio_error("%s %d: %s\n", + "error in ioctl CDROMREADTOCENTRY for track", + i, strerror(errno)); + return false; + } + /**** + struct cdrom_msf0 *msf= &_obj->tocent[i-1].cdte_addr.msf; + + fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", + i, msf->minute, msf->second, msf->frame); + ****/ + + } + + /* read the lead-out track */ + _obj->tocent[TOTAL_TRACKS].cdte_track = CDROM_LEADOUT; + _obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF; + + if (ioctl(_obj->fd, CDROMREADTOCENTRY, + &_obj->tocent[TOTAL_TRACKS]) == -1 ) { + cdio_error("%s: %s\n", + "error in ioctl CDROMREADTOCENTRY for lead-out", + strerror(errno)); + return false; + } + + /* + struct cdrom_msf0 *msf= &_obj->tocent[TOTAL_TRACKS].cdte_addr.msf; + + fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", + i, msf->minute, msf->second, msf->frame); + */ + + return true; +} + +/*! + Eject media in CD drive. If successful, as a side effect we + also free obj. + */ +static int +_cdio_eject_media (void *user_data) { + + _img_private_t *_obj = user_data; + int ret=2; + int status; + int fd; + + if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) { + if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) { + switch(status) { + case CDS_TRAY_OPEN: + if((ret = ioctl(fd, CDROMCLOSETRAY, 0)) != 0) { + cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); + } + break; + case CDS_DISC_OK: + if((ret = ioctl(fd, CDROMEJECT, 0)) != 0) { + cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(errno)); + } + break; + } + ret=0; + } else { + cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); + ret=1; + } + close(fd); + _cdio_free((void *) _obj); + } + return 2; +} + +/*! + Return the value associated with the key "arg". +*/ +static const char * +_cdio_get_arg (void *user_data, const char key[]) +{ + _img_private_t *_obj = user_data; + + if (!strcmp (key, "source")) { + return _obj->source_name; + } else if (!strcmp (key, "access-mode")) { + switch (_obj->access_mode) { + case _AM_IOCTL: + return "ioctl"; + case _AM_NONE: + return "no access method"; + } + } + return NULL; +} + +/*! + Return a string containing the default VCD device if none is specified. + */ +static char * +_cdio_get_default_device() +{ + return strdup(DEFAULT_CDIO_DEVICE); +} + +/*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. +*/ +static track_t +_cdio_get_first_track_num(void *user_data) +{ + _img_private_t *_obj = user_data; + + if (!_obj->toc_init) _cdio_read_toc (_obj) ; + + return FIRST_TRACK_NUM; +} + +/*! + Return the number of tracks in the current medium. + CDIO_INVALID_TRACK is returned on error. +*/ +static track_t +_cdio_get_num_tracks(void *user_data) +{ + _img_private_t *_obj = user_data; + + if (!_obj->toc_init) _cdio_read_toc (_obj) ; + + return TOTAL_TRACKS; +} + +/*! + Get format of track. +*/ +static track_format_t +_cdio_get_track_format(void *user_data, track_t track_num) +{ + _img_private_t *_obj = user_data; + + if (!_obj->toc_init) _cdio_read_toc (_obj) ; + + if (track_num > TOTAL_TRACKS || track_num == 0) + return TRACK_FORMAT_ERROR; + + /* This is pretty much copied from the "badly broken" cdrom_count_tracks + in linux/cdrom.c. + */ + if (_obj->tocent[track_num-1].cdte_ctrl & CDROM_DATA_TRACK) { + if (_obj->tocent[track_num-1].cdte_format == 0x10) + return TRACK_FORMAT_CDI; + else if (_obj->tocent[track_num-1].cdte_format == 0x20) + return TRACK_FORMAT_XA; + else + return TRACK_FORMAT_DATA; + } else + return TRACK_FORMAT_AUDIO; + +} + +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? +*/ +static bool +_cdio_get_track_green(void *user_data, track_t track_num) +{ + _img_private_t *_obj = user_data; + + if (!_obj->toc_init) _cdio_read_toc (_obj) ; + + if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + + if (track_num > TOTAL_TRACKS+1 || track_num == 0) + return false; + + /* FIXME: Dunno if this is the right way, but it's what + I was using in cdinfo for a while. + */ + return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0); +} + +/*! + Return the starting MSF (minutes/secs/frames) for track number + track_num in obj. Track numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + False is returned if there is no track entry. +*/ +static bool +_cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf) +{ + _img_private_t *_obj = user_data; + + if (NULL == msf) return false; + + if (!_obj->toc_init) _cdio_read_toc (_obj) ; + + if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + + if (track_num > TOTAL_TRACKS+1 || track_num == 0) { + return false; + } else { + struct cdrom_msf0 *msf0= &_obj->tocent[track_num-1].cdte_addr.msf; + msf->m = to_bcd8(msf0->minute); + msf->s = to_bcd8(msf0->second); + msf->f = to_bcd8(msf0->frame); + return true; + } +} + #endif /* HAVE_BSDI_CDROM */ +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ CdIo * cdio_open_bsdi (const char *source_name) { #ifdef HAVE_BSDI_CDROM + CdIo *ret; _img_private_t *_data; cdio_funcs _funcs = { @@ -400,13 +515,20 @@ cdio_open_bsdi (const char *source_name) .free = _cdio_free, .get_arg = _cdio_get_arg, .get_default_device = _cdio_get_default_device, + .get_first_track_num= _cdio_get_first_track_num, + .get_num_tracks = _cdio_get_num_tracks, + .get_track_format = _cdio_get_track_format, + .get_track_green = _cdio_get_track_green, + .get_track_lba = NULL, /* This could be implemented if need be. */ + .get_track_msf = _cdio_get_track_msf, .read_mode2_sector = _read_mode2_sector, + .read_mode2_sectors = _read_mode2_sectors, .set_arg = _cdio_set_arg, .stat_size = _cdio_stat_size }; _data = _cdio_malloc (sizeof (_img_private_t)); - _data->access_mode = _AM_READ_CD; + _data->access_mode = _AM_IOCTL; _data->init = false; _data->fd = -1; @@ -426,8 +548,8 @@ cdio_open_bsdi (const char *source_name) #else return NULL; #endif /* HAVE_BSDI_CDROM */ -} +} bool cdio_have_bsdi (void) diff --git a/lib/_cdio_bsdi_old.c b/lib/_cdio_bsdi_old.c new file mode 100644 index 00000000..83439f1e --- /dev/null +++ b/lib/_cdio_bsdi_old.c @@ -0,0 +1,443 @@ +/* + $Id: _cdio_bsdi_old.c,v 1.1 2003/03/29 17:32:00 rocky Exp $ + + Copyright (C) 2001 Herbert Valerio Riedel + Copyright (C) 2003 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "cdio_assert.h" +#include "cdio_private.h" +#include "util.h" +#include "sector.h" +#include "logging.h" + +#include +#include +#include + +static const char _rcsid[] = "$Id: _cdio_bsdi_old.c,v 1.1 2003/03/29 17:32:00 rocky Exp $"; + +#if HAVE_BSDI_CDROM + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define DEFAULT_CDIO_DEVICE "/dev/rsr0c" + +/* reader */ + +typedef struct { + int fd; + + enum { + _AM_NONE, + _AM_READ_CD, + _AM_READ_10 + } access_mode; + + char *source_name; + + bool init; +} _img_private_t; + +static int +_scsi_cmd (int fd, struct scsi_user_cdb *sucp, const char *tag) +{ + u_char *cp; + + if (ioctl (fd, SCSIRAWCDB, sucp)) + { + vcd_error ("%s: ioctl (SCSIRAWCDB): %s", tag, strerror (errno)); + return 1; + } + if (sucp->suc_sus.sus_status) + { + cp = sucp->suc_sus.sus_sense; + vcd_info("%s: cmd: %x sus_status %d ", tag, sucp->suc_cdb[0], + sucp->suc_sus.sus_status); + vcd_info(" sense: %x %x %x %x %x %x %x %x", cp[0], cp[1], cp[2], + cp[3], cp[4], cp[5], cp[6], cp[7]); + return 1; + } + return 0; +} + +/*! + Initialize CD device. + */ +static bool +_cdio_init (_img_private_t *_obj) +{ + if (_obj->init) + return; + + _obj->fd = open (_obj->source_name, O_RDONLY, 0); + _obj->access_mode = _AM_READ_CD; + + if (_obj->fd < 0) + { + cdio_error ("open (%s): %s", _obj->source_name, strerror (errno)); + return false; + } + + _obj->init = true; + _obj->toc_init = false; + return true; +} + + +/*! + Release and free resources associated with cd. + */ +static void +_cdio_free (void *user_data) +{ + _img_private_t *_obj = user_data; + + free (_obj->source_name); + + if (_obj->fd) + close (_obj->fd); + + free (_obj); +} + +static int +_set_bsize (int fd, unsigned int bsize) +{ + struct + { + uint8_t reserved1; + uint8_t medium; + uint8_t reserved2; + uint8_t block_desc_length; + uint8_t density; + uint8_t number_of_blocks_hi; + uint8_t number_of_blocks_med; + uint8_t number_of_blocks_lo; + uint8_t reserved3; + uint8_t block_length_hi; + uint8_t block_length_med; + uint8_t block_length_lo; + } mh; + + struct scsi_user_cdb suc; + + memset (&mh, 0, sizeof (mh)); + memset (&suc, 0, sizeof (struct scsi_user_cdb)); + + suc.suc_cdb[0] = 0x15; + suc.suc_cdb[1] = 1 << 4; + suc.suc_cdb[4] = 12; + suc.suc_cdblen = 6;; + + suc.suc_data = (u_char *)&mh; + suc.suc_datalen = sizeof (mh); + + suc.suc_timeout = 500; + suc.suc_flags = SUC_WRITE; + + mh.block_desc_length = 0x08; + mh.block_length_hi = (bsize >> 16) & 0xff; + mh.block_length_med = (bsize >> 8) & 0xff; + mh.block_length_lo = (bsize >> 0) & 0xff; + + return _scsi_cmd (fd, &suc, "_set_bsize"); +} + +static int +_read_mode2 (int fd, void *buf, uint32_t lba, unsigned nblocks, + bool _workaround) +{ + struct scsi_user_cdb suc; + int retval = 0; + + memset (&suc, 0, sizeof (struct scsi_user_cdb)); + + suc.suc_cdb[0] = (_workaround + ? 0x28 /* CMD_READ_10 */ + : 0xbe /* CMD_READ_CD */); + + if (!_workaround) + suc.suc_cdb[1] = 0; /* sector size mode2 */ + + suc.suc_cdb[2] = (lba >> 24) & 0xff; + suc.suc_cdb[3] = (lba >> 16) & 0xff; + suc.suc_cdb[4] = (lba >> 8) & 0xff; + suc.suc_cdb[5] = (lba >> 0) & 0xff; + + suc.suc_cdb[6] = (nblocks >> 16) & 0xff; + suc.suc_cdb[7] = (nblocks >> 8) & 0xff; + suc.suc_cdb[8] = (nblocks >> 0) & 0xff; + + if (!_workaround) + suc.suc_cdb[9] = 0x58; /* 2336 mode2 mixed form */ + + suc.suc_cdblen = _workaround ? 10 : 12; + + suc.suc_data = buf; + suc.suc_datalen = 2336 * nblocks; + + suc.suc_timeout = 500; + suc.suc_flags = SUC_READ; + + if (_workaround) + { + if ((retval = _set_bsize (fd, 2336))) + goto out; + + if ((retval = _scsi_cmd(fd, &suc, "_read_mode2_workaround"))) + { + _set_bsize (fd, 2048); + goto out; + } + retval = _set_bsize (fd, 2048); + } + else + retval = _scsi_cmd(fd, &suc, "_read_mode2"); + + out: + return retval; +} + +static int +_read_mode2_sector (void *user_data, void *data, uint32_t lsn, bool form2) +{ + _img_private_t *_obj = user_data; + + _cdio_init (_obj); + + if (form2) + { + retry: + switch (_obj->access_mode) + { + case _AM_NONE: + vcd_error ("no way to read mode2"); + return 1; + break; + + case _AM_READ_CD: + case _AM_READ_10: + if (_read_mode2 (_obj->fd, data, lsn, 1, + (_obj->access_mode == _AM_READ_10))) + { + if (_obj->access_mode == _AM_READ_CD) + { + vcd_info ("READ_CD failed; switching to READ_10 mode..."); + _obj->access_mode = _AM_READ_10; + goto retry; + } + else + { + vcd_info ("READ_10 failed; no way to read mode2 left."); + _obj->access_mode = _AM_NONE; + goto retry; + } + return 1; + } + break; + } + } + else + { + char buf[M2RAW_SIZE] = { 0, }; + int retval; + + if ((retval = _read_mode2_sector (_obj, buf, lsn, true))) + return retval; + + memcpy (data, buf + 8, M2F1_SECTOR_SIZE); + } + + return 0; +} + +static const u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; + +static uint32_t +_cdio_stat_size (void *user_data) +{ + _img_private_t *_obj = user_data; + + struct scsi_user_cdb suc; + uint8_t buf[12] = { 0, }; + + uint32_t retval; + + _cdio_init(_obj); + + memset (&suc, 0, sizeof (struct scsi_user_cdb)); + + suc.suc_cdb[0] = 0x43; /* CMD_READ_TOC_PMA_ATIP */ + suc.suc_cdb[1] = 0; /* lba; msf: 0x2 */ + suc.suc_cdb[6] = 0xaa; /* CDROM_LEADOUT */ + suc.suc_cdb[8] = 12; /* ? */ + suc.suc_cdblen = 10; + + suc.suc_data = buf; + suc.suc_datalen = sizeof (buf); + + suc.suc_timeout = 500; + suc.suc_flags = SUC_READ; + + if (_scsi_cmd(_obj->fd, &suc, "_cdio_stat_size")) + return 0; + + { + int i; + + retval = 0; + for (i = 8; i < 12; i++) + { + retval <<= 8; + retval += buf[i]; + } + } + + return retval; +} + +/*! + Return the value associated with the key "arg". +*/ +static const char * +_cdio_get_arg (void *user_data, const char key[]) +{ + _img_private_t *_obj = user_data; + + if (!strcmp (key, "source")) { + return _obj->source_name; + } else if (!strcmp (key, "access-mode")) { + switch (_obj->access_mode) { + case _AM_READ_CD: + return "READ_CD"; + case _AM_READ_10: + return "READ_10"; + case _AM_NONE: + return "no access method"; + } + } + return NULL; +} + +/*! + Return a string containing the default VCD device if none is specified. + */ +static char * +_cdio_get_default_device() +{ + return strdup(DEFAULT_CDIO_DEVICE); +} + +/*! + Set the key "arg" to "value" in source device. +*/ +static int +_cdio_set_arg (void *user_data, const char key[], const char value[]) +{ + _img_private_t *_obj = user_data; + + if (!strcmp (key, "source")) + { + if (!value) + return -2; + + free (_obj->source_name); + + _obj->source_name = strdup (value); + } + else if (!strcmp (key, "access-mode")) + { + if (!strcmp(value, "READ_CD")) + _obj->access_mode = _AM_READ_CD; + else if (!strcmp(value, "READ_10")) + _obj->access_mode = _AM_READ_10; + else + cdio_error ("unknown access type: %s. ignored.", value); + } + else + return -1; + + return 0; +} + +#endif /* HAVE_BSDI_CDROM */ + +CdIo * +cdio_open_bsdi (const char *source_name) +{ + +#ifdef HAVE_BSDI_CDROM + _img_private_t *_data; + + cdio_funcs _funcs = { + .eject_media = _cdio_eject_media, + .free = _cdio_free, + .get_arg = _cdio_get_arg, + .get_default_device = _cdio_get_default_device, + .read_mode2_sector = _read_mode2_sector, + .set_arg = _cdio_set_arg, + .stat_size = _cdio_stat_size + }; + + _data = _cdio_malloc (sizeof (_img_private_t)); + _data->access_mode = _AM_READ_CD; + _data->init = false; + _data->fd = -1; + + _cdio_set_arg(_data, "source", (NULL == source_name) + ? DEFAULT_CDIO_DEVICE: source_name); + + ret = cdio_new (_data, &_funcs); + if (ret == NULL) return NULL; + + if (_cdio_init(_data)) + return ret; + else { + _cdio_free (_data); + return NULL; + } + +#else + return NULL; +#endif /* HAVE_BSDI_CDROM */ +} + + +bool +cdio_have_bsdi (void) +{ +#ifdef HAVE_BSDI_CDROM + return true; +#else + return false; +#endif /* HAVE_BSDI_CDROM */ +} + diff --git a/lib/_cdio_freebsd.c b/lib/_cdio_freebsd.c index 8bd707ae..3397a98d 100644 --- a/lib/_cdio_freebsd.c +++ b/lib/_cdio_freebsd.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_freebsd.c,v 1.1 2003/03/25 00:00:36 rocky Exp $ + $Id: _cdio_freebsd.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2003 Rocky Bernstein @@ -26,7 +26,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_freebsd.c,v 1.1 2003/03/25 00:00:36 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_freebsd.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; #include "cdio_assert.h" #include "cdio_private.h" @@ -209,7 +209,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, if (mode2_form2) memcpy (data, buf, M2RAW_SECTOR_SIZE); else - memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE); + memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE); return 0; } diff --git a/lib/_cdio_generic.c b/lib/_cdio_generic.c new file mode 100644 index 00000000..174c671f --- /dev/null +++ b/lib/_cdio_generic.c @@ -0,0 +1,110 @@ +/* + $Id: _cdio_generic.c,v 1.1 2003/03/29 17:32:00 rocky Exp $ + + Copyright (C) 2001 Herbert Valerio Riedel + Copyright (C) 2002,2003 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains Linux-specific code and implements low-level + control of the CD drive. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.1 2003/03/29 17:32:00 rocky Exp $"; + +#include "cdio_assert.h" +#include "cdio_private.h" +#include "sector.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*! + Release and free resources associated with cd. + */ +void +cdio_generic_free (void *user_data) +{ + generic_img_private_t *_obj = user_data; + + if (NULL == _obj) return; + free (_obj->source_name); + + if (_obj->fd >= 0) + close (_obj->fd); + + free (_obj); +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). +*/ +off_t +cdio_generic_lseek (void *user_data, off_t offset, int whence) +{ + generic_img_private_t *_obj = user_data; + return lseek(_obj->fd, offset, whence); +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). +*/ +ssize_t +cdio_generic_read (void *user_data, void *buf, size_t size) +{ + generic_img_private_t *_obj = user_data; + return read(_obj->fd, buf, size); +} + + +int +cdio_generic_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, + bool mode2raw, unsigned num_sectors) +{ + char *_buf = buf; + const int blocksize = mode2raw ? M2RAW_SECTOR_SIZE : M2F1_SECTOR_SIZE; + int n, rc; + + cdio_assert (obj != NULL); + cdio_assert (buf != NULL); + cdio_assert (obj->op.read_mode2_sector != NULL); + + for (n = 0; n < num_sectors; n++) + if ((rc = cdio_read_mode2_sector (obj, &_buf[n * blocksize], + lsn + n, mode2raw))) + return rc; + + return 0; +} + diff --git a/lib/_cdio_linux.c b/lib/_cdio_linux.c index 3f197cae..f21c7690 100644 --- a/lib/_cdio_linux.c +++ b/lib/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.2 2003/03/24 23:59:22 rocky Exp $ + $Id: _cdio_linux.c,v 1.3 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002,2003 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2003/03/24 23:59:22 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.3 2003/03/29 17:32:00 rocky Exp $"; #include "cdio_assert.h" #include "cdio_private.h" @@ -65,9 +65,9 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2003/03/24 23:59:22 rocky #define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) typedef struct { - int fd; - - int ioctls_debugged; /* for debugging */ + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; enum { _AM_NONE, @@ -76,9 +76,7 @@ typedef struct { _AM_READ_10 } access_mode; - char *source_name; - - bool init; + int ioctls_debugged; /* for debugging */ /* Track information */ bool toc_init; /* if true, info below is valid. */ @@ -93,41 +91,24 @@ typedef struct { static bool _cdio_init (_img_private_t *_obj) { - if (_obj->init) { + if (_obj->gen.init) { cdio_error ("init called more than once"); return false; } - _obj->fd = open (_obj->source_name, O_RDONLY, 0); + _obj->gen.fd = open (_obj->gen.source_name, O_RDONLY, 0); - if (_obj->fd < 0) + if (_obj->gen.fd < 0) { - cdio_error ("open (%s): %s", _obj->source_name, strerror (errno)); + cdio_error ("open (%s): %s", _obj->gen.source_name, strerror (errno)); return false; } - _obj->init = true; + _obj->gen.init = true; _obj->toc_init = false; return true; } -/*! - Release and free resources associated with cd. - */ -static void -_cdio_free (void *user_data) -{ - _img_private_t *_obj = user_data; - - if (NULL == _obj) return; - free (_obj->source_name); - - if (_obj->fd >= 0) - close (_obj->fd); - - free (_obj); -} - static int _set_bsize (int fd, unsigned int bsize) { @@ -254,8 +235,8 @@ _read_mode2 (int fd, void *buf, lba_t lba, unsigned nblocks, from lsn. Returns 0 if no error. */ static int -_read_mode2_sector (void *user_data, void *data, lsn_t lsn, - bool mode2_form2) +_cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn, + bool mode2_form2) { char buf[M2RAW_SECTOR_SIZE] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; @@ -292,7 +273,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, break; case _AM_IOCTL: - if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1) + if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl()"); return 1; @@ -302,7 +283,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, case _AM_READ_CD: case _AM_READ_10: - if (_read_mode2 (_obj->fd, buf, lsn, 1, + if (_read_mode2 (_obj->gen.fd, buf, lsn, 1, (_obj->access_mode == _AM_READ_10))) { perror ("ioctl()"); @@ -326,7 +307,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, if (mode2_form2) memcpy (data, buf, M2RAW_SECTOR_SIZE); else - memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE); + memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE); return 0; } @@ -337,8 +318,8 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_read_mode2_sectors (void *user_data, void *data, lsn_t lsn, - bool mode2_form2, unsigned nblocks) +_cdio_read_mode2_sectors (void *user_data, void *data, lsn_t lsn, + bool mode2_form2, unsigned nblocks) { _img_private_t *_obj = user_data; int i; @@ -346,17 +327,18 @@ _read_mode2_sectors (void *user_data, void *data, lsn_t lsn, for (i = 0; i < nblocks; i++) { if (mode2_form2) { - if ( (retval = _read_mode2_sector (_obj, - ((char *)data) + (M2RAW_SECTOR_SIZE * i), - lsn + i, true)) ) + if ( (retval = _cdio_read_mode2_sector (_obj, + ((char *)data) + + (M2RAW_SECTOR_SIZE * i), + lsn + i, true)) ) return retval; } else { char buf[M2RAW_SECTOR_SIZE] = { 0, }; - if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) ) + if ( (retval = _cdio_read_mode2_sector (_obj, buf, lsn + i, true)) ) return retval; - memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8, - M2F1_SECTOR_SIZE); + memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8, + FORM1_DATA_SIZE); } } return 0; @@ -375,7 +357,7 @@ _cdio_stat_size (void *user_data) tocent.cdte_track = CDROM_LEADOUT; tocent.cdte_format = CDROM_LBA; - if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1) + if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); @@ -399,9 +381,9 @@ _cdio_set_arg (void *user_data, const char key[], const char value[]) if (!value) return -2; - free (_obj->source_name); + free (_obj->gen.source_name); - _obj->source_name = strdup (value); + _obj->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { @@ -430,7 +412,7 @@ _cdio_read_toc (_img_private_t *_obj) int i; /* read TOC header */ - if ( ioctl(_obj->fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { + if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { cdio_error("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; @@ -440,7 +422,7 @@ _cdio_read_toc (_img_private_t *_obj) for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) { _obj->tocent[i-1].cdte_track = i; _obj->tocent[i-1].cdte_format = CDROM_MSF; - if ( ioctl(_obj->fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { + if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { cdio_error("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); @@ -459,7 +441,7 @@ _cdio_read_toc (_img_private_t *_obj) _obj->tocent[TOTAL_TRACKS].cdte_track = CDROM_LEADOUT; _obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF; - if (ioctl(_obj->fd, CDROMREADTOCENTRY, + if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[TOTAL_TRACKS]) == -1 ) { cdio_error("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", @@ -489,7 +471,7 @@ _cdio_eject_media (void *user_data) { int status; int fd; - if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) { + if ((fd = open (_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) { switch(status) { case CDS_TRAY_OPEN: @@ -509,7 +491,7 @@ _cdio_eject_media (void *user_data) { ret=1; } close(fd); - _cdio_free((void *) _obj); + cdio_generic_free((void *) _obj); } return 2; } @@ -523,7 +505,7 @@ _cdio_get_arg (void *user_data, const char key[]) _img_private_t *_obj = user_data; if (!strcmp (key, "source")) { - return _obj->source_name; + return _obj->gen.source_name; } else if (!strcmp (key, "access-mode")) { switch (_obj->access_mode) { case _AM_IOCTL: @@ -676,7 +658,7 @@ cdio_open_linux (const char *source_name) cdio_funcs _funcs = { .eject_media = _cdio_eject_media, - .free = _cdio_free, + .free = cdio_generic_free, .get_arg = _cdio_get_arg, .get_default_device = _cdio_get_default_device, .get_first_track_num= _cdio_get_first_track_num, @@ -685,16 +667,18 @@ cdio_open_linux (const char *source_name) .get_track_green = _cdio_get_track_green, .get_track_lba = NULL, /* This could be implemented if need be. */ .get_track_msf = _cdio_get_track_msf, - .read_mode2_sector = _read_mode2_sector, - .read_mode2_sectors = _read_mode2_sectors, + .lseek = cdio_generic_lseek, + .read = cdio_generic_read, + .read_mode2_sector = _cdio_read_mode2_sector, + .read_mode2_sectors = _cdio_read_mode2_sectors, .set_arg = _cdio_set_arg, .stat_size = _cdio_stat_size }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_READ_CD; - _data->init = false; - _data->fd = -1; + _data->gen.init = false; + _data->gen.fd = -1; _cdio_set_arg(_data, "source", (NULL == source_name) ? DEFAULT_CDIO_DEVICE: source_name); @@ -705,7 +689,7 @@ cdio_open_linux (const char *source_name) if (_cdio_init(_data)) return ret; else { - _cdio_free (_data); + cdio_generic_free (_data); return NULL; } diff --git a/lib/_cdio_nrg.c b/lib/_cdio_nrg.c index 3eb86e25..0ee6e0c4 100644 --- a/lib/_cdio_nrg.c +++ b/lib/_cdio_nrg.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_nrg.c,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_nrg.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001,2003 Herbert Valerio Riedel @@ -38,7 +38,7 @@ #include "util.h" #include "_cdio_stdio.h" -static const char _rcsid[] = "$Id: _cdio_nrg.c,v 1.1 2003/03/24 19:01:09 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_nrg.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; /* structures used */ @@ -102,9 +102,9 @@ typedef struct { int track_num; /* Probably is index+1 */ msf_t start_msf; int start_index; - int secsize; /* Number of sectors in track. Does not - include pregap before next entry. */ - int flags; /* "DCP", "4CH", "PRE" */ + int sec_count; /* Number of sectors in track. Does not + include pregap before next entry. */ + int flags; /* "DCP", "4CH", "PRE" */ track_format_t track_format; bool track_green; } track_info_t; @@ -114,15 +114,15 @@ typedef struct { Possibly redundant with above track_info_t */ typedef struct { uint32_t start_lsn; - uint32_t secsize; /* Number of sectors in track. Does not - include pregap before next entry. */ - uint64_t img_offset; /* Bytes offset from beginning of disk image file.*/ + uint32_t sec_count; /* Number of sectors in track. Does not + include pregap before next entry. */ + uint64_t img_offset; /* Bytes offset from beginning of disk image file.*/ } _mapping_t; typedef struct { bool sector_2336_flag; - CdioDataSource *nrg_src; + CdioDataSource *data_source; char *source_name; track_info_t tocent[100]; /* entry info for each track */ track_t total_tracks; /* number of tracks in image */ @@ -145,8 +145,8 @@ _cdio_free (void *user_data) free(_obj->source_name); - if (_obj->nrg_src) - cdio_stream_destroy (_obj->nrg_src); + if (_obj->data_source) + cdio_stream_destroy (_obj->data_source); _cdio_list_free (_obj->mapping, true); @@ -157,7 +157,7 @@ _cdio_free (void *user_data) simulate ioctl(CDROMREADTOCENTRY). */ static void -_register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t secsize, +_register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t sec_count, uint64_t img_offset, uint32_t blocksize) { const int track_num=_obj->total_tracks; @@ -167,11 +167,11 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t secsize, _obj->mapping = _cdio_list_new (); _cdio_list_append (_obj->mapping, _map); - _map->start_lsn = start_lsn; - _map->secsize = secsize; + _map->start_lsn = start_lsn; + _map->sec_count = sec_count; _map->img_offset = img_offset; - _obj->size = MAX (_obj->size, (start_lsn + secsize)); + _obj->size = MAX (_obj->size, (start_lsn + sec_count)); /* Update _obj->tocent[track_num] and track_num These structures are in a sense redundant witht the obj->mapping list. Perhaps one @@ -183,8 +183,7 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t secsize, _obj->tocent[track_num].track_num = track_num+1; _obj->tocent[track_num].blocksize = blocksize; - _obj->tocent[track_num].secsize = secsize; - _obj->tocent[track_num].secsize = secsize; + _obj->tocent[track_num].sec_count = sec_count; _obj->total_tracks++; @@ -195,7 +194,7 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t secsize, _obj->tocent[track_num].track_green = true; - /* cdio_debug ("map: %d +%d -> %ld", start_lsn, secsize, img_offset); */ + /* cdio_debug ("map: %d +%d -> %ld", start_lsn, sec_count, img_offset); */ } @@ -213,7 +212,7 @@ _cdio_parse_nero_footer (_img_private_t *_obj) if (_obj->size) return 0; - size = cdio_stream_stat (_obj->nrg_src); + size = cdio_stream_stat (_obj->data_source); { PRAGMA_BEGIN_PACKED @@ -231,9 +230,9 @@ PRAGMA_BEGIN_PACKED PRAGMA_END_PACKED cdio_assert (sizeof (buf) == 12); - - cdio_stream_seek (_obj->nrg_src, size - sizeof (buf)); - cdio_stream_read (_obj->nrg_src, (void *) &buf, sizeof (buf), 1); + + cdio_stream_seek (_obj->data_source, size - sizeof (buf), SEEK_SET); + cdio_stream_read (_obj->data_source, (void *) &buf, sizeof (buf), 1); if (buf.v50.ID == UINT32_TO_BE (0x4e45524f)) /* "NERO" */ { @@ -258,8 +257,8 @@ PRAGMA_END_PACKED footer_buf = _cdio_malloc (size - footer_start); - cdio_stream_seek (_obj->nrg_src, footer_start); - cdio_stream_read (_obj->nrg_src, footer_buf, size - footer_start, 1); + cdio_stream_seek (_obj->data_source, footer_start, SEEK_SET); + cdio_stream_read (_obj->data_source, footer_buf, size - footer_start, 1); } { @@ -487,7 +486,7 @@ _cdio_init (_img_private_t *_obj) return false; } - if (!(_obj->nrg_src = cdio_stdio_new (_obj->source_name))) { + if (!(_obj->data_source = cdio_stdio_new (_obj->source_name))) { cdio_error ("init failed"); return false; } @@ -498,6 +497,76 @@ _cdio_init (_img_private_t *_obj) } +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Would be libc's seek() but we have to adjust for the extra track header + information in each sector. +*/ +static off_t +_cdio_lseek (void *user_data, off_t offset, int whence) +{ + _img_private_t *_obj = user_data; + + /* real_offset is the real byte offset inside the disk image + The number below was determined empirically. I'm guessing + the 1st 24 bytes of a bin file are used for something. + */ + off_t real_offset=8; + + unsigned int i; + unsigned int user_datasize; + + for (i=0; i<_obj->total_tracks; i++) { + track_info_t *this_track=&(_obj->tocent[i]); + switch (this_track->track_format) { + case TRACK_FORMAT_AUDIO: + user_datasize=CDDA_SECTOR_SIZE; + break; + case TRACK_FORMAT_CDI: + user_datasize=FORM1_DATA_SIZE; + break; + case TRACK_FORMAT_XA: + user_datasize=FORM1_DATA_SIZE; + break; + default: + cdio_warn ("track %d has unknown format %d", + i+1, this_track->track_format); + } + + if ( (this_track->sec_count*user_datasize) >= offset) { + int blocks = offset / user_datasize; + int rem = offset % user_datasize; + int block_offset = blocks * (M2RAW_SECTOR_SIZE); + real_offset += block_offset + rem; + break; + } + real_offset += this_track->sec_count*(M2RAW_SECTOR_SIZE); + + offset -= this_track->sec_count*user_datasize; + } + + if (i==_obj->total_tracks) { + cdio_warn ("seeking outside range of disk image"); + return -1; + } else + return cdio_stream_seek(_obj->data_source, real_offset, whence); +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + FIXME: + At present we assume a read doesn't cross sector or track + boundaries. +*/ +static ssize_t +_cdio_read (void *user_data, void *buf, size_t size) +{ + _img_private_t *_obj = user_data; + return cdio_stream_read(_obj->data_source, buf, size, 1); +} + static uint32_t _cdio_stat_size (void *user_data) { @@ -524,7 +593,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, bool form2) { _mapping_t *_map = _cdio_list_node_data (node); - if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->secsize - 1))) + if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { long img_offset = _map->img_offset; int blocksize = _obj->sector_2336_flag @@ -532,8 +601,8 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, bool form2) img_offset += (lsn - _map->start_lsn) * blocksize; - cdio_stream_seek (_obj->nrg_src, img_offset); - cdio_stream_read (_obj->nrg_src, + cdio_stream_seek (_obj->data_source, img_offset, SEEK_SET); + cdio_stream_read (_obj->data_source, _obj->sector_2336_flag ? (buf + 12 + 4) : buf, blocksize, 1); @@ -547,7 +616,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, bool form2) if (form2) memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE); else - memcpy (data, buf + 12 + 4 + 8, M2F1_SECTOR_SIZE); + memcpy (data, buf + 12 + 4 + 8, FORM1_DATA_SIZE); return 0; } @@ -576,8 +645,8 @@ _read_mode2_sectors (void *user_data, void *data, uint32_t lsn, if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) ) return retval; - memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8, - M2F1_SECTOR_SIZE); + memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8, + FORM1_DATA_SIZE); } } return 0; @@ -700,6 +769,8 @@ _cdio_get_track_green(void *user_data, track_t track_num) /*! Return the starting MSF (minutes/secs/frames) for the track number track_num in obj. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. */ static bool _cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf) @@ -732,8 +803,10 @@ cdio_open_nrg (const char *source_name) .get_num_tracks = _cdio_get_num_tracks, .get_track_format = _cdio_get_track_format, .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* This could be implemented if need be. */ + .get_track_lba = NULL, /* Will use generic routine via msf */ .get_track_msf = _cdio_get_track_msf, + .lseek = _cdio_lseek, + .read = _cdio_read, .read_mode2_sector = _read_mode2_sector, .read_mode2_sectors = _read_mode2_sectors, .set_arg = _cdio_set_arg, diff --git a/lib/_cdio_stdio.c b/lib/_cdio_stdio.c index 711ff2ee..18704de5 100644 --- a/lib/_cdio_stdio.c +++ b/lib/_cdio_stdio.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_stdio.c,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_stdio.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -35,7 +35,7 @@ #include "_cdio_stream.h" #include "_cdio_stdio.h" -static const char _rcsid[] = "$Id: _cdio_stdio.c,v 1.1 2003/03/24 19:01:09 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_stdio.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; #define CDIO_STDIO_BUFSIZE (128*1024) @@ -91,11 +91,11 @@ _stdio_free(void *user_data) } static long -_stdio_seek(void *user_data, long offset) +_stdio_seek(void *user_data, long offset, int whence) { _UserData *const ud = user_data; - if (fseek (ud->fd, offset, SEEK_SET)) + if (fseek (ud->fd, offset, whence)) cdio_error ("fseek (): %s", strerror (errno)); return offset; diff --git a/lib/_cdio_stream.c b/lib/_cdio_stream.c index 9268fef2..a91df5c4 100644 --- a/lib/_cdio_stream.c +++ b/lib/_cdio_stream.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_stream.c,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_stream.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel @@ -34,7 +34,7 @@ #include "util.h" #include "_cdio_stream.h" -static const char _rcsid[] = "$Id: _cdio_stream.c,v 1.1 2003/03/24 19:01:09 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_stream.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; /* * DataSource implementations @@ -66,7 +66,7 @@ _cdio_stream_open_if_necessary(CdioDataSource *obj) } long -cdio_stream_seek(CdioDataSource* obj, long offset) +cdio_stream_seek(CdioDataSource* obj, long offset, int whence) { cdio_assert (obj != NULL); @@ -77,7 +77,7 @@ cdio_stream_seek(CdioDataSource* obj, long offset) cdio_warn("had to reposition DataSource from %ld to %ld!", obj->position, offset); #endif obj->position = offset; - return obj->op.seek(obj->user_data, offset); + return obj->op.seek(obj->user_data, offset, whence); } return 0; diff --git a/lib/_cdio_stream.h b/lib/_cdio_stream.h index 0e0b97b9..769475ee 100644 --- a/lib/_cdio_stream.h +++ b/lib/_cdio_stream.h @@ -1,5 +1,5 @@ /* - $Id: _cdio_stream.h,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_stream.h,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -35,7 +35,7 @@ typedef int(*cdio_data_open_t)(void *user_data); typedef long(*cdio_data_read_t)(void *user_data, void *buf, long count); -typedef long(*cdio_data_seek_t)(void *user_data, long offset); +typedef long(*cdio_data_seek_t)(void *user_data, long offset, int whence); typedef long(*cdio_data_stat_t)(void *user_data); @@ -64,7 +64,7 @@ long cdio_stream_read(CdioDataSource* obj, void *ptr, long size, long nmemb); long -cdio_stream_seek(CdioDataSource* obj, long offset); +cdio_stream_seek(CdioDataSource* obj, long offset, int whence); long cdio_stream_stat(CdioDataSource* obj); diff --git a/lib/_cdio_sunos.c b/lib/_cdio_sunos.c index 7eabf48f..8bc3a233 100644 --- a/lib/_cdio_sunos.c +++ b/lib/_cdio_sunos.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_sunos.c,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: _cdio_sunos.c,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002,2003 Rocky Bernstein @@ -31,7 +31,7 @@ #ifdef HAVE_SOLARIS_CDROM -static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.1 2003/03/24 19:01:09 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.2 2003/03/29 17:32:00 rocky Exp $"; #include #include @@ -62,10 +62,10 @@ static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.1 2003/03/24 19:01:09 rocky /* reader */ typedef struct { - int fd; - - int ioctls_debugged; /* for debugging */ - + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; + enum { _AM_NONE, _AM_SUN_CTRL_ATAPI, @@ -76,9 +76,8 @@ typedef struct { #endif } access_mode; - char *source_name; - - bool init; + + int ioctls_debugged; /* for debugging */ /* Track information */ bool toc_init; /* if true, info below is valid. */ @@ -96,9 +95,9 @@ _cdio_init (_img_private_t *_obj) struct dk_cinfo cinfo; - _obj->fd = open (_obj->source_name, O_RDONLY, 0); + _obj->gen.fd = open (_obj->source_name, O_RDONLY, 0); - if (_obj->fd < 0) + if (_obj->gen.fd < 0) { cdio_error ("open (%s): %s", _obj->source_name, strerror (errno)); return false; @@ -109,7 +108,7 @@ _cdio_init (_img_private_t *_obj) * Try to send MMC3 SCSI commands via the uscsi interface on * ATAPI devices. */ - if ( ioctl(_obj->fd, DKIOCINFO, &cinfo) == 0 + if ( ioctl(_obj->gen.fd, DKIOCINFO, &cinfo) == 0 && ((strcmp(cinfo.dki_cname, "ide") == 0) || (strncmp(cinfo.dki_cname, "pci", 3) == 0)) ) { _obj->access_mode = _AM_SUN_CTRL_ATAPI; @@ -117,30 +116,12 @@ _cdio_init (_img_private_t *_obj) _obj->access_mode = _AM_SUN_CTRL_SCSI; } - _obj->init = true; + _obj->gen.init = true; _obj->toc_init = false; return true; } - -/*! - Release and free resources associated with cd. - */ -static void -_cdio_free (void *user_data) -{ - _img_private_t *_obj = user_data; - - if (NULL == _obj) return; - free (_obj->source_name); - - if (_obj->fd >= 0) - close (_obj->fd); - - free (_obj); -} - /*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. @@ -183,7 +164,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, break; case _AM_SUN_CTRL_SCSI: - if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1) { + if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl(..,CDROMREADMODE2,..)"); return 1; /* exit (EXIT_FAILURE); */ @@ -236,7 +217,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, sc.uscsi_buflen = M2RAW_SECTOR_SIZE; sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ; sc.uscsi_timeout = 20; - if (ioctl(_obj->fd, USCSICMD, &sc)) { + if (ioctl(_obj->gen.fd, USCSICMD, &sc)) { perror("USCSICMD: READ CD"); return 1; } @@ -252,7 +233,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, if (mode2_form2) memcpy (data, buf, M2RAW_SECTOR_SIZE); else - memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE); + memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE); return 0; } @@ -281,8 +262,8 @@ _read_mode2_sectors (void *user_data, void *data, uint32_t lsn, if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) ) return retval; - memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8, - M2F1_SECTOR_SIZE); + memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8, + FORM1_DATA_SIZE); } } return 0; @@ -301,7 +282,7 @@ _cdio_stat_size (void *user_data) tocent.cdte_track = CDROM_LEADOUT; tocent.cdte_format = CDROM_LBA; - if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1) + if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); @@ -354,7 +335,7 @@ _cdio_read_toc (_img_private_t *_obj) int i; /* read TOC header */ - if ( ioctl(_obj->fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { + if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { cdio_error("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; @@ -364,7 +345,7 @@ _cdio_read_toc (_img_private_t *_obj) for (i=_obj->tochdr.cdth_trk0; i<=_obj->tochdr.cdth_trk1; i++) { _obj->tocent[i-1].cdte_track = i; _obj->tocent[i-1].cdte_format = CDROM_MSF; - if ( ioctl(_obj->fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { + if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { cdio_error("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); @@ -376,7 +357,7 @@ _cdio_read_toc (_img_private_t *_obj) _obj->tocent[_obj->tochdr.cdth_trk1].cdte_track = CDROM_LEADOUT; _obj->tocent[_obj->tochdr.cdth_trk1].cdte_format = CDROM_MSF; - if (ioctl(_obj->fd, CDROMREADTOCENTRY, + if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[_obj->tochdr.cdth_trk1]) == -1 ) { cdio_error("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", @@ -397,13 +378,13 @@ _cdio_eject_media (void *user_data) { _img_private_t *_obj = user_data; int ret; - if (_obj->fd > -1) { - if ((ret = ioctl(_obj->fd, CDROMEJECT)) != 0) { - _cdio_free((void *) _obj); + if (_obj->gen.fd > -1) { + if ((ret = ioctl(_obj->gen.fd, CDROMEJECT)) != 0) { + cdio_generic_free((void *) _obj); cdio_error ("CDROMEJECT failed: %s\n", strerror(errno)); return 1; } else { - _cdio_free((void *) _obj); + cdio_generic_free((void *) _obj); return 0; } } @@ -515,7 +496,7 @@ _cdio_get_track_format(void *user_data, track_t track_num) { _img_private_t *_obj = user_data; - if (!_obj->init) _cdio_init(_obj); + if (!_obj->gen.init) _cdio_init(_obj); if (!_obj->toc_init) _cdio_read_toc (_obj) ; if (track_num > TOTAL_TRACKS || track_num == 0) @@ -549,7 +530,7 @@ _cdio_get_track_green(void *user_data, track_t track_num) { _img_private_t *_obj = user_data; - if (!_obj->init) _cdio_init(_obj); + if (!_obj->gen.init) _cdio_init(_obj); if (!_obj->toc_init) _cdio_read_toc (_obj) ; if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; @@ -568,7 +549,7 @@ _cdio_get_track_green(void *user_data, track_t track_num) track_num in obj. Tracks numbers start at 1. The "leadout" track is specified either by using track_num LEADOUT_TRACK or the total tracks+1. - NULL is returned if there is no entry. + False is returned if there is no entry. */ static bool _cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf) @@ -577,7 +558,7 @@ _cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf) if (NULL == msf) return false; - if (!_obj->init) _cdio_init(_obj); + if (!_obj->gen.init) _cdio_init(_obj); if (!_obj->toc_init) _cdio_read_toc (_obj) ; if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; @@ -610,14 +591,17 @@ cdio_open_solaris (const char *source_name) cdio_funcs _funcs = { .eject_media = _cdio_eject_media, - .free = _cdio_free, + .free = cdio_generic_free, .get_arg = _cdio_get_arg, .get_default_device = _cdio_get_default_device, .get_first_track_num= _cdio_get_first_track_num, .get_num_tracks = _cdio_get_num_tracks, .get_track_format = _cdio_get_track_format, .get_track_green = _cdio_get_track_green, + .get_track_lba = NULL, /* This could be implemented if need be. */ .get_track_msf = _cdio_get_track_msf, + .lseek = cdio_generic_lseek, + .read = cdio_generic_read, .read_mode2_sector = _read_mode2_sector, .read_mode2_sectors = _read_mode2_sectors, .stat_size = _cdio_stat_size, @@ -636,7 +620,7 @@ cdio_open_solaris (const char *source_name) if (_cdio_init(_data)) return ret; else { - _cdio_free (_data); + cdio_generic_free (_data); return NULL; } diff --git a/lib/cdio.c b/lib/cdio.c index 94044df1..bb2cf3ba 100644 --- a/lib/cdio.c +++ b/lib/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.2 2003/03/24 23:59:22 rocky Exp $ + $Id: cdio.c,v 1.3 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2003 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -28,7 +28,7 @@ #include "logging.h" #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.2 2003/03/24 23:59:22 rocky Exp $"; +static const char _rcsid[] = "$Id: cdio.c,v 1.3 2003/03/29 17:32:00 rocky Exp $"; const char *track_format2str[5] = @@ -41,11 +41,6 @@ const char *track_format2str[5] = CdIo_driver_t CdIo_driver[MAX_DRIVER] = { {0} }; -struct _CdIo { - void *user_data; - cdio_funcs op; -}; - /* The last valid entry of Cdio_driver. -1 means uninitialzed. -2 means some sort of error. */ @@ -189,7 +184,7 @@ cdio_get_first_track_num (const CdIo *obj) track_t cdio_get_num_tracks (const CdIo *obj) { - cdio_assert (obj != NULL); + if (obj == NULL) return CDIO_INVALID_TRACK; if (obj->op.get_num_tracks) { return obj->op.get_num_tracks (obj->user_data); @@ -233,6 +228,28 @@ cdio_get_track_green(const CdIo *obj, track_t track_num) } } +/*! + Return the starting LBA for track number + track_num in obj. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LBA is returned on error. +*/ +lba_t +cdio_get_track_lba(const CdIo *obj, track_t track_num) +{ + if (obj == NULL) return CDIO_INVALID_LBA; + + if (obj->op.get_track_lba) { + return obj->op.get_track_lba (obj->user_data, track_num); + } else { + msf_t msf; + if (cdio_get_track_msf(obj, track_num, &msf)) + return cdio_msf_to_lba(&msf); + return CDIO_INVALID_LBA; + } +} + /*! Return the starting MSF (minutes/secs/frames) for track number track_num in obj. Track numbers start at 1. @@ -241,7 +258,7 @@ cdio_get_track_green(const CdIo *obj, track_t track_num) False is returned if there is no track entry. */ bool -cdio_get_track_msf(const CdIo *obj, track_t track_num, msf_t *msf) +cdio_get_track_msf(const CdIo *obj, track_t track_num, /*out*/ msf_t *msf) { cdio_assert (obj != NULL); @@ -252,6 +269,23 @@ cdio_get_track_msf(const CdIo *obj, track_t track_num, msf_t *msf) } } +/*! + Return the number of sectors between this track an the next. This + includes any pregap sectors before the start of the next track. + Tracks start at 1. + 0 is returned if there is an error. +*/ +unsigned int +cdio_get_track_sec_count(const CdIo *obj, track_t track_num) +{ + track_t num_tracks = cdio_get_num_tracks(obj); + + if (track_num >=1 && track_num <= num_tracks) + return ( cdio_get_track_lba(obj, track_num+1) + - cdio_get_track_lba(obj, track_num) ); + return 0; +} + bool cdio_have_driver(driver_id_t driver_id) { @@ -300,6 +334,9 @@ cdio_new (void *user_data, const cdio_funcs *funcs) return new_obj; } +/*! + Free any resources associated with obj. +*/ void cdio_destroy (CdIo *obj) { @@ -309,31 +346,46 @@ cdio_destroy (CdIo *obj) free (obj); } +/*! + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to (if not the same as) libc's lseek() +*/ +off_t +cdio_lseek (CdIo *obj, off_t offset, int whence) +{ + if (obj == NULL) return -1; + + if (obj->op.lseek) + return obj->op.lseek (obj->user_data, offset, whence); + return -1; +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Similar to (if not the same as) libc's read() +*/ +ssize_t +cdio_read (CdIo *obj, void *buf, size_t size) +{ + if (obj == NULL) return -1; + + if (obj->op.read) + return obj->op.read (obj->user_data, buf, size); + return -1; +} + int cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool mode2raw, unsigned num_sectors) { - char *_buf = buf; - const int blocksize = mode2raw ? M2RAW_SECTOR_SIZE : M2F1_SECTOR_SIZE; - int n, rc; - cdio_assert (obj != NULL); cdio_assert (buf != NULL); - cdio_assert (obj->op.read_mode2_sector != NULL - || obj->op.read_mode2_sectors != NULL); + cdio_assert (obj->op.read_mode2_sectors != NULL); - if (obj->op.read_mode2_sectors) - return obj->op.read_mode2_sectors (obj->user_data, buf, lsn, - mode2raw, num_sectors); - - /* fallback */ - if (obj->op.read_mode2_sector != NULL) - for (n = 0; n < num_sectors; n++) - if ((rc = cdio_read_mode2_sector (obj, &_buf[n * blocksize], - lsn + n, mode2raw))) - return rc; - - return 0; + return obj->op.read_mode2_sectors (obj->user_data, buf, lsn, + mode2raw, num_sectors); } /*! diff --git a/lib/cdio.h b/lib/cdio.h index 0c8becf2..492bed36 100644 --- a/lib/cdio.h +++ b/lib/cdio.h @@ -1,5 +1,5 @@ /* - $Id: cdio.h,v 1.2 2003/03/24 23:59:22 rocky Exp $ + $Id: cdio.h,v 1.3 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -25,6 +25,13 @@ #ifndef __CDIO_H__ #define __CDIO_H__ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + #include "cdio_types.h" #include "sector.h" @@ -78,7 +85,10 @@ extern "C" { Return 0 if success and 1 for failure, and 2 if no routine. */ int cdio_eject_media (const CdIo *obj); - + + /*! + Free any resources associated with obj. + */ void cdio_destroy (CdIo *obj); /*! @@ -117,6 +127,15 @@ extern "C" { */ bool cdio_get_track_green(const CdIo *obj, track_t track_num); + /*! + Return the starting LBA for track number + track_num in obj. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LBA is returned on error. + */ + lba_t cdio_get_track_lba(const CdIo *obj, track_t track_num); + /*! Return the starting MSF (minutes/secs/frames) for track number track_num in obj. Track numbers start at 1. @@ -124,8 +143,31 @@ extern "C" { using track_num LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ - bool cdio_get_track_msf(const CdIo *obj, track_t track_num, msf_t *msf); + bool cdio_get_track_msf(const CdIo *obj, track_t track_num, + /*out*/ msf_t *msf); + /*! + Return the number of sectors between this track an the next. This + includes any pregap sectors before the start of the next track. + Tracks start at 1. + 0 is returned if there is an error. + */ + unsigned int cdio_get_track_sec_count(const CdIo *obj, track_t track_num); + + /*! + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to (if not the same as) libc's lseek() + */ + off_t cdio_lseek(CdIo *obj, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Similar to (if not the same as) libc's read() + */ + ssize_t cdio_read(CdIo *obj, void *buf, size_t size); + /*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. diff --git a/lib/cdio_private.h b/lib/cdio_private.h index 4ba84617..fcb2bc43 100644 --- a/lib/cdio_private.h +++ b/lib/cdio_private.h @@ -1,5 +1,5 @@ /* - $Id: cdio_private.h,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: cdio_private.h,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2003 Rocky Bernstein @@ -24,6 +24,13 @@ #ifndef __CDIO_PRIVATE_H__ #define __CDIO_PRIVATE_H__ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + #include #ifdef __cplusplus @@ -66,13 +73,13 @@ extern "C" { track_t (*get_num_tracks) (void *user_data); /*! - Return the starting MSF (minutes/secs/frames) for track number + Return the starting LBA for track number track_num in obj. Tracks numbers start at 1. The "leadout" track is specified either by using track_num LEADOUT_TRACK or the total tracks+1. - 1 is returned on error. + CDIO_INVALID_LBA is returned on error. */ - uint32_t (*get_track_lba) (void *user_data, track_t track_num); + lba_t (*get_track_lba) (void *user_data, track_t track_num); /*! Get format of track. @@ -94,12 +101,26 @@ extern "C" { track_num in obj. Tracks numbers start at 1. The "leadout" track is specified either by using track_num LEADOUT_TRACK or the total tracks+1. - 1 is returned on error. + False is returned on error. */ bool (*get_track_msf) (void *user_data, track_t track_num, msf_t *msf); /*! - Reads a single mode2 sector from cd device into data starting + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to libc's lseek() + */ + off_t (*lseek) (void *user_data, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Similar to libc's read() + */ + ssize_t (*read) (void *user_data, void *buf, size_t size); + + /*! + Reads a single mode2 sector from cd device into buf starting from lsn. Returns 0 if no error. */ int (*read_mode2_sector) (void *user_data, void *buf, lsn_t lsn, @@ -124,7 +145,15 @@ extern "C" { uint32_t (*stat_size) (void *user_data); } cdio_funcs; - + + + /* Things that just about all private device structures have. */ + typedef struct { + char *source_name; /* Name used in open. */ + bool init; /* True if structure has been initialized */ + int fd; /* File descriptor of device */ + } generic_img_private_t; + CdIo * cdio_new (void *user_data, const cdio_funcs *funcs); /* The below structure describes a specific CD Input driver */ @@ -151,6 +180,39 @@ extern "C" { on a particular host. */ extern CdIo_driver_t CdIo_all_drivers[MAX_DRIVER+1]; + /*! + Release and free resources associated with cd. + */ + void cdio_generic_free (void *user_data); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + off_t cdio_generic_lseek (void *user_data, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + ssize_t cdio_generic_read (void *user_data, void *buf, size_t size); + + /*! + Reads nblocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ + int cdio_generic_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, + bool mode2raw, unsigned num_sectors); + + struct _CdIo { + void *user_data; + cdio_funcs op; + }; + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lib/cdio_types.h b/lib/cdio_types.h index 0154822f..1e68dfab 100644 --- a/lib/cdio_types.h +++ b/lib/cdio_types.h @@ -1,5 +1,5 @@ /* - $Id: cdio_types.h,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: cdio_types.h,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2002,2003 Rocky Bernstein @@ -201,6 +201,11 @@ typedef uint8_t track_t; */ #define CDIO_INVALID_TRACK 0xFF +/*! + Constant for invalid LBA +*/ +#define CDIO_INVALID_LBA 0xFFFFFFFF + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lib/sector.h b/lib/sector.h index 303f2935..c3c15da3 100644 --- a/lib/sector.h +++ b/lib/sector.h @@ -1,5 +1,5 @@ /* - $Id: sector.h,v 1.1 2003/03/24 19:01:09 rocky Exp $ + $Id: sector.h,v 1.2 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003 Rocky Bernstein @@ -44,7 +44,7 @@ * format sector type user data size (bytes) * ----------------------------------------------------------------------------- * 1 (Red Book) CD-DA 2352 (CDDA_SECTOR_SIZE) - * 2 (Yellow Book) Mode1 Form1 2048 (M2F1_SECTOR_SIZE) + * 2 (Yellow Book) Mode1 Form1 2048 (M1F1_SECTOR_SIZE) * 3 (Yellow Book) Mode1 Form2 2336 (M2RAW_SECTOR_SIZE) * 4 (Green Book) Mode2 Form1 2048 (M2F1_SECTOR_SIZE) * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) @@ -71,7 +71,9 @@ #define CD_RAW_SECTOR_SIZE 2352 #define CDDA_SECTOR_SIZE CD_RAW_SECTOR_SIZE +#define M1F1_SECTOR_SIZE 2048 #define M2F1_SECTOR_SIZE 2048 +#define FORM1_DATA_SIZE 2048 /* Mode 1 or Mode 2 user data */ #define M2F2_SECTOR_SIZE 2324 #define M2SUB_SECTOR_SIZE 2332 #define M2RAW_SECTOR_SIZE 2336 diff --git a/src/Makefile.am b/src/Makefile.am index 1823c459..7b50db17 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.1 2003/03/24 19:01:09 rocky Exp $ +# $Id: Makefile.am,v 1.2 2003/03/29 17:32:00 rocky Exp $ # # Copyright (C) 2003 Rocky Bernstein # @@ -25,8 +25,14 @@ cdinfo_linux_SOURCES = cdinfo-linux.c cdinfo_linux_LDADD = $(LIBCDIO_LIBS) -lpopt else EXTRA_DIST = cdinfo-linux.c +if BUILD_CDIOTEST +bin_PROGRAMS = cdinfo cdiotest +cdiotest_SOURCES = cdiotest.c +cdiotest_LDADD = $(LIBCDIO_LIBS) +else bin_PROGRAMS = cdinfo endif +endif INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS) diff --git a/src/cdinfo.c b/src/cdinfo.c index 0368c0ac..eb2b7a7c 100644 --- a/src/cdinfo.c +++ b/src/cdinfo.c @@ -1,5 +1,5 @@ /* - $Id: cdinfo.c,v 1.3 2003/03/25 02:10:41 rocky Exp $ + $Id: cdinfo.c,v 1.4 2003/03/29 17:32:00 rocky Exp $ Copyright (C) 2003 Rocky Bernstein Copyright (C) 1996,1997,1998 Gerd Knorr @@ -408,13 +408,24 @@ PARTICULAR PURPOSE.\n\ /* some ISO 9660 fiddling */ static int -read_block(int superblock, uint32_t offset, uint8_t bufnum, bool is_green) +read_block(int superblock, uint32_t offset, uint8_t bufnum, track_t track_num) { + unsigned int track_sec_count = cdio_get_track_sec_count(img, track_num); memset(buffer[bufnum],0,M2F1_SECTOR_SIZE); + + if ( track_sec_count < superblock) { + dbg_print(1, "reading block %u skipped track %d has only %u sectors\n", + superblock, track_num, track_sec_count); + return -1; + } dbg_print(2, "about to read sector %u\n", offset+superblock); - if (cdio_read_mode2_sector(img, buffer[bufnum], - offset+superblock, !is_green)) + + if (0 > cdio_lseek(img, FORM1_DATA_SIZE*(offset+superblock),SEEK_SET)) + return -1; + + + if (0 > cdio_read(img, buffer[bufnum], FORM1_DATA_SIZE)) return -1; return 0; @@ -479,11 +490,11 @@ get_joliet_level( void ) if (is_it(sig)) printf("%s, ", sigs[sig].description) static int -guess_filesystem(int start_session, bool is_green) +guess_filesystem(int start_session, track_t track_num) { int ret = 0; - if (read_block(ISO_SUPERBLOCK_SECTOR, start_session, 0, is_green) < 0) + if (read_block(ISO_SUPERBLOCK_SECTOR, start_session, 0, track_num) < 0) return FS_UNKNOWN; if (opts.debug_level > 0) { @@ -504,7 +515,7 @@ guess_filesystem(int start_session, bool is_green) return FS_INTERACTIVE; } else { /* read sector 0 ONLY, when NO greenbook CD-I !!!! */ - if (read_block(0, start_session, 1, true) < 0) + if (read_block(0, start_session, 1, track_num) < 0) return ret; if (opts.debug_level > 0) { @@ -532,7 +543,7 @@ guess_filesystem(int start_session, bool is_green) ret |= ROCKRIDGE; #endif - if (read_block(BOOT_SECTOR, start_session, 3, true) < 0) + if (read_block(BOOT_SECTOR, start_session, 3, track_num) < 0) return ret; if (opts.debug_level > 0) { @@ -555,7 +566,7 @@ guess_filesystem(int start_session, bool is_green) && is_it(IS_CD_RTOS) && !is_it(IS_PHOTO_CD)) { - if (read_block(VCD_INFO_SECTOR, start_session, 4, true) < 0) + if (read_block(VCD_INFO_SECTOR, start_session, 4, track_num) < 0) return ret; if (opts.debug_level > 0) { @@ -571,8 +582,7 @@ guess_filesystem(int start_session, bool is_green) else if (is_it(IS_EXT2)) ret |= FS_EXT2; else if (is_3do()) ret |= FS_3DO; else { - - if (read_block(UFS_SUPERBLOCK_SECTOR, start_session, 2, true) < 0) + if (read_block(UFS_SUPERBLOCK_SECTOR, start_session, 2, track_num) < 0) return ret; if (opts.debug_level > 0) { @@ -933,12 +943,14 @@ main(int argc, const char *argv[]) /* CD-I/Ready says start_track <= 30*75 then CDDA */ if (start_track > 100 /* 100 is just a guess */) { - fs = guess_filesystem(0, false); + fs = guess_filesystem(0, 1); if ((fs & FS_MASK) != FS_UNKNOWN) fs |= HIDDEN_TRACK; else { fs &= ~FS_MASK; /* del filesystem info */ - printf("Oops: %i unused sectors at start, but hidden track check failed.\n",start_track); + printf("Oops: %i unused sectors at start, " + "but hidden track check failed.\n", + start_track); } } print_analysis(fs, num_audio); @@ -971,7 +983,7 @@ main(int argc, const char *argv[]) if (start_track < data_start + isofs_size) continue; - fs = guess_filesystem(start_track, cdio_get_track_green(img, i)); + fs = guess_filesystem(start_track, i); if (i > 1) { /* track is beyond last session -> new session found */ diff --git a/tests/monvoisin.right b/tests/monvoisin.right index 7d474c30..56f1a843 100644 --- a/tests/monvoisin.right +++ b/tests/monvoisin.right @@ -14,4 +14,4 @@ CD-ROM with CD-RTOS and ISO 9660 filesystem ISO 9660: 1101 blocks, label `MONVOISIN ' XA sectors Video CD session #2 starts at track 2, LSN: 1251, ISO 9660 blocks: 1101 -ISO 9660: 1101 blocks, label `' +ISO 9660: 1101 blocks, label `)*c]dq^\MvKMbǍ%'