Add simple (non-mode2) read/seek.
_cdio_generic.c: place to save common driver routines add cdio_get_track_sec_count.
This commit is contained in:
@@ -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)
|
AC_INIT(lib/cdio.c)
|
||||||
AM_CONFIG_HEADER(config.h)
|
AM_CONFIG_HEADER(config.h)
|
||||||
AM_INIT_AUTOMAKE(libcdio, 0.1)
|
AM_INIT_AUTOMAKE(libcdio, 0.1)
|
||||||
@@ -118,7 +118,8 @@ LIBS="$LIBS -lm"
|
|||||||
CFLAGS="$CFLAGS $WARN_CFLAGS"
|
CFLAGS="$CFLAGS $WARN_CFLAGS"
|
||||||
|
|
||||||
AM_CONDITIONAL(CYGWIN, test "x$CYGWIN" = "xyes")
|
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
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
|
|||||||
@@ -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 <rocky@panix.com>
|
# Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
#
|
#
|
||||||
@@ -29,6 +29,7 @@ libcdio_sources = \
|
|||||||
_cdio_bincue.c \
|
_cdio_bincue.c \
|
||||||
_cdio_bsdi.c \
|
_cdio_bsdi.c \
|
||||||
_cdio_freebsd.c \
|
_cdio_freebsd.c \
|
||||||
|
_cdio_generic.c \
|
||||||
_cdio_linux.c \
|
_cdio_linux.c \
|
||||||
_cdio_nrg.c \
|
_cdio_nrg.c \
|
||||||
_cdio_stdio.c \
|
_cdio_stdio.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 <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#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 <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -49,9 +49,12 @@ static const char _rcsid[] = "$Id: _cdio_bincue.c,v 1.1 2003/03/24 19:01:09 rock
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int blocksize;
|
int blocksize;
|
||||||
int track_num; /* Probably is index+1 */
|
int track_num; /* Probably is index+1 */
|
||||||
msf_t start_msf;
|
msf_t start_msf;
|
||||||
|
lba_t start_lba;
|
||||||
int start_index;
|
int start_index;
|
||||||
|
int sec_count; /* Number of sectors in this track. Does not
|
||||||
|
include pregap */
|
||||||
int num_indices;
|
int num_indices;
|
||||||
int flags; /* "DCP", "4CH", "PRE" */
|
int flags; /* "DCP", "4CH", "PRE" */
|
||||||
track_format_t track_format;
|
track_format_t track_format;
|
||||||
@@ -61,16 +64,16 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
char *source_name;
|
||||||
|
bool init;
|
||||||
bool sector_2336_flag;
|
bool sector_2336_flag;
|
||||||
|
|
||||||
CdioDataSource *bin_src;
|
CdioDataSource *data_source;
|
||||||
char *source_name;
|
|
||||||
char *cue_name;
|
char *cue_name;
|
||||||
track_info_t tocent[100]; /* entry info for each track */
|
track_info_t tocent[100]; /* entry info for each track */
|
||||||
track_t total_tracks; /* number of tracks in image */
|
track_t total_tracks; /* number of tracks in image */
|
||||||
track_t first_track_num; /* track number of first track */
|
track_t first_track_num; /* track number of first track */
|
||||||
bool have_cue;
|
bool have_cue;
|
||||||
bool init;
|
|
||||||
} _img_private_t;
|
} _img_private_t;
|
||||||
|
|
||||||
static bool _cdio_image_read_cue (_img_private_t *_obj);
|
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
|
static bool
|
||||||
_cdio_init (_img_private_t *_obj)
|
_cdio_init (_img_private_t *_obj)
|
||||||
{
|
{
|
||||||
|
lsn_t lead_lsn;
|
||||||
|
|
||||||
if (_obj->init)
|
if (_obj->init)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Read in CUE sheet. */
|
if (!(_obj->data_source = cdio_stdio_new (_obj->source_name))) {
|
||||||
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))) {
|
|
||||||
cdio_error ("init failed");
|
cdio_error ("init failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -121,12 +100,113 @@ _cdio_init (_img_private_t *_obj)
|
|||||||
*/
|
*/
|
||||||
_obj->init = true;
|
_obj->init = true;
|
||||||
|
|
||||||
/* Fake out leadout track. */
|
lead_lsn = _cdio_stat_size( (_img_private_t *) _obj);
|
||||||
cdio_lsn_to_msf ( _cdio_stat_size( (_img_private_t *) _obj),
|
|
||||||
&_obj->tocent[_obj->total_tracks].start_msf);
|
/* 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;
|
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);
|
_cdio_init (_obj);
|
||||||
|
|
||||||
size = cdio_stream_stat (_obj->bin_src);
|
size = cdio_stream_stat (_obj->data_source);
|
||||||
|
|
||||||
if (size % blocksize)
|
if (size % blocksize)
|
||||||
{
|
{
|
||||||
@@ -194,48 +274,79 @@ _cdio_image_read_cue (_img_private_t *_obj)
|
|||||||
*/
|
*/
|
||||||
/* printf("Found file name %s\n", s); */
|
/* printf("Found file name %s\n", s); */
|
||||||
} else if (2==sscanf(p, "TRACK %d MODE2/%d", &track_num, &blocksize)) {
|
} else if (2==sscanf(p, "TRACK %d MODE2/%d", &track_num, &blocksize)) {
|
||||||
_obj->tocent[_obj->total_tracks].blocksize = blocksize;
|
track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]);
|
||||||
_obj->tocent[_obj->total_tracks].track_num = track_num;
|
this_track->blocksize = blocksize;
|
||||||
_obj->tocent[_obj->total_tracks].num_indices = 0;
|
this_track->track_num = track_num;
|
||||||
_obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_XA;
|
this_track->num_indices = 0;
|
||||||
_obj->tocent[_obj->total_tracks].track_green = true;
|
this_track->track_format= TRACK_FORMAT_XA;
|
||||||
|
this_track->track_green = true;
|
||||||
_obj->total_tracks++;
|
_obj->total_tracks++;
|
||||||
seen_first_index_for_track=false;
|
seen_first_index_for_track=false;
|
||||||
/*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/
|
/*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/
|
||||||
|
|
||||||
} else if (2==sscanf(p, "TRACK %d MODE1/%d", &track_num, &blocksize)) {
|
} else if (2==sscanf(p, "TRACK %d MODE1/%d", &track_num, &blocksize)) {
|
||||||
_obj->tocent[_obj->total_tracks].blocksize = blocksize;
|
track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]);
|
||||||
_obj->tocent[_obj->total_tracks].track_num = track_num;
|
this_track->blocksize = blocksize;
|
||||||
_obj->tocent[_obj->total_tracks].num_indices = 0;
|
this_track->track_num = track_num;
|
||||||
_obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_CDI;
|
this_track->num_indices = 0;
|
||||||
_obj->tocent[_obj->total_tracks].track_green = false;
|
this_track->track_format= TRACK_FORMAT_CDI;
|
||||||
|
this_track->track_green = false;
|
||||||
_obj->total_tracks++;
|
_obj->total_tracks++;
|
||||||
seen_first_index_for_track=false;
|
seen_first_index_for_track=false;
|
||||||
/*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/
|
/*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/
|
||||||
|
|
||||||
} else if (1==sscanf(p, "TRACK %d AUDIO", &track_num)) {
|
} else if (1==sscanf(p, "TRACK %d AUDIO", &track_num)) {
|
||||||
_obj->tocent[_obj->total_tracks].blocksize = blocksize;
|
track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]);
|
||||||
_obj->tocent[_obj->total_tracks].track_num = track_num;
|
this_track->blocksize = CDDA_SECTOR_SIZE;
|
||||||
_obj->tocent[_obj->total_tracks].num_indices = 0;
|
this_track->track_num = track_num;
|
||||||
_obj->tocent[_obj->total_tracks].track_format= TRACK_FORMAT_AUDIO;
|
this_track->num_indices = 0;
|
||||||
_obj->tocent[_obj->total_tracks].track_green = false;
|
this_track->track_format= TRACK_FORMAT_AUDIO;
|
||||||
|
this_track->track_green = false;
|
||||||
_obj->total_tracks++;
|
_obj->total_tracks++;
|
||||||
seen_first_index_for_track=false;
|
seen_first_index_for_track=false;
|
||||||
|
|
||||||
} else if (4==sscanf(p, "INDEX %d %d:%d:%d",
|
} else if (4==sscanf(p, "INDEX %d %d:%d:%d",
|
||||||
&start_index, &min, &sec, &frame)) {
|
&start_index, &min, &sec, &frame)) {
|
||||||
|
track_info_t *this_track=&(_obj->tocent[_obj->total_tracks-1]);
|
||||||
/* FIXME! all of this is a big hack.
|
/* FIXME! all of this is a big hack.
|
||||||
If start_index == 0, then this is the "last_cue" information.
|
If start_index == 0, then this is the "last_cue" information.
|
||||||
The +2 below seconds is to adjust for the 150 pregap.
|
The +2 below seconds is to adjust for the 150 pregap.
|
||||||
*/
|
*/
|
||||||
if (!seen_first_index_for_track && start_index != 0) {
|
if (start_index != 0) {
|
||||||
_obj->tocent[_obj->total_tracks-1].start_index = start_index;
|
if (!seen_first_index_for_track) {
|
||||||
_obj->tocent[_obj->total_tracks-1].start_msf.m = to_bcd8 (min);
|
this_track->start_index = start_index;
|
||||||
_obj->tocent[_obj->total_tracks-1].start_msf.s = to_bcd8 (sec)+2;
|
this_track->start_msf.m = to_bcd8 (min);
|
||||||
_obj->tocent[_obj->total_tracks-1].start_msf.f = to_bcd8 (frame);
|
this_track->start_msf.s = to_bcd8 (sec)+2;
|
||||||
seen_first_index_for_track=true;
|
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;
|
_obj->have_cue = _obj->total_tracks != 0;
|
||||||
@@ -254,8 +365,8 @@ _cdio_free (void *user_data)
|
|||||||
|
|
||||||
free (_obj->source_name);
|
free (_obj->source_name);
|
||||||
|
|
||||||
if (_obj->bin_src)
|
if (_obj->data_source)
|
||||||
cdio_stream_destroy (_obj->bin_src);
|
cdio_stream_destroy (_obj->data_source);
|
||||||
|
|
||||||
free (_obj);
|
free (_obj);
|
||||||
}
|
}
|
||||||
@@ -271,16 +382,16 @@ _read_mode2_sector (void *user_data, void *data, uint32_t lsn,
|
|||||||
|
|
||||||
_cdio_init (_obj);
|
_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,
|
_obj->sector_2336_flag ? (buf + 12 + 4) : buf,
|
||||||
blocksize, 1);
|
blocksize, 1);
|
||||||
|
|
||||||
if (mode2_form2)
|
if (mode2_form2)
|
||||||
memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE);
|
memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
memcpy (data, buf + 12 + 4 + 8, M2F1_SECTOR_SIZE);
|
memcpy (data, buf + 12 + 4 + 8, FORM1_DATA_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -310,7 +421,7 @@ _read_mode2_sectors (void *user_data, void *data, uint32_t lsn,
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8,
|
memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8,
|
||||||
M2F1_SECTOR_SIZE);
|
FORM1_DATA_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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 _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
|
Return the starting MSF (minutes/secs/frames) for the track number
|
||||||
track_num in obj. Tracks numbers start at 1.
|
track_num in obj. Tracks numbers start at 1.
|
||||||
Since there are no tracks, unless the track number is is 1 we return
|
The "leadout" track is specified either by
|
||||||
falure. If the track number is 1, we return 00:00:00.
|
using track_num LEADOUT_TRACK or the total tracks+1.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
_cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf)
|
_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_num_tracks = _cdio_get_num_tracks,
|
||||||
.get_track_format = _cdio_get_track_format,
|
.get_track_format = _cdio_get_track_format,
|
||||||
.get_track_green = _cdio_get_track_green,
|
.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,
|
.get_track_msf = _cdio_get_track_msf,
|
||||||
.read_mode2_sector = _read_mode2_sector,
|
.read_mode2_sector = _read_mode2_sector,
|
||||||
.read_mode2_sectors = _read_mode2_sectors,
|
.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_num_tracks = _cdio_get_num_tracks,
|
||||||
.get_track_format = _cdio_get_track_format,
|
.get_track_format = _cdio_get_track_format,
|
||||||
.get_track_green = _cdio_get_track_green,
|
.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,
|
.get_track_msf = _cdio_get_track_msf,
|
||||||
|
.lseek = _cdio_lseek,
|
||||||
|
.read = _cdio_read,
|
||||||
.read_mode2_sector = _read_mode2_sector,
|
.read_mode2_sector = _read_mode2_sector,
|
||||||
.read_mode2_sectors = _read_mode2_sectors,
|
.read_mode2_sectors = _read_mode2_sectors,
|
||||||
.set_arg = _cdio_set_arg,
|
.set_arg = _cdio_set_arg,
|
||||||
|
|||||||
630
lib/_cdio_bsdi.c
630
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 <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
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
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#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_assert.h"
|
||||||
#include "cdio_private.h"
|
#include "cdio_private.h"
|
||||||
#include "util.h"
|
|
||||||
#include "sector.h"
|
#include "sector.h"
|
||||||
#include "logging.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_BSDI_CDROM
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2003/03/24 23:59:22 rocky Exp $";
|
|
||||||
|
|
||||||
#if HAVE_BSDI_CDROM
|
|
||||||
|
|
||||||
#include </sys/dev/scsi/scsi.h>
|
|
||||||
#include </sys/dev/scsi/scsi_ioctl.h>
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
/* reader */
|
#include <dvd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#define DEFAULT_CDIO_DEVICE "/dev/sr0"
|
||||||
|
|
||||||
|
#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1)
|
||||||
|
#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
int ioctls_debugged; /* for debugging */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_AM_NONE,
|
_AM_NONE,
|
||||||
_AM_READ_CD,
|
_AM_IOCTL,
|
||||||
_AM_READ_10
|
|
||||||
} access_mode;
|
} access_mode;
|
||||||
|
|
||||||
char *source_name;
|
char *source_name;
|
||||||
|
|
||||||
bool init;
|
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;
|
} _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.
|
Initialize CD device.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
_cdio_init (_img_private_t *_obj)
|
_cdio_init (_img_private_t *_obj)
|
||||||
{
|
{
|
||||||
if (_obj->init)
|
if (_obj->init) {
|
||||||
return;
|
cdio_error ("init called more than once");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_obj->fd = open (_obj->source_name, O_RDONLY, 0);
|
_obj->fd = open (_obj->source_name, O_RDONLY, 0);
|
||||||
_obj->access_mode = _AM_READ_CD;
|
|
||||||
|
|
||||||
if (_obj->fd < 0)
|
if (_obj->fd < 0)
|
||||||
{
|
{
|
||||||
@@ -109,7 +98,6 @@ _cdio_init (_img_private_t *_obj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Release and free resources associated with cd.
|
Release and free resources associated with cd.
|
||||||
*/
|
*/
|
||||||
@@ -118,240 +106,128 @@ _cdio_free (void *user_data)
|
|||||||
{
|
{
|
||||||
_img_private_t *_obj = user_data;
|
_img_private_t *_obj = user_data;
|
||||||
|
|
||||||
|
if (NULL == _obj) return;
|
||||||
free (_obj->source_name);
|
free (_obj->source_name);
|
||||||
|
|
||||||
if (_obj->fd)
|
if (_obj->fd >= 0)
|
||||||
close (_obj->fd);
|
close (_obj->fd);
|
||||||
|
|
||||||
free (_obj);
|
free (_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Reads a single mode2 sector from cd device into data starting
|
||||||
|
from lsn. Returns 0 if no error.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
_set_bsize (int fd, unsigned int bsize)
|
_read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
||||||
|
bool mode2_form2)
|
||||||
{
|
{
|
||||||
struct
|
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
||||||
{
|
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
|
||||||
uint8_t reserved1;
|
msf_t _msf;
|
||||||
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;
|
_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:
|
case _AM_NONE:
|
||||||
switch (_obj->access_mode)
|
cdio_error ("no way to read mode2");
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _AM_IOCTL:
|
||||||
|
if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1)
|
||||||
{
|
{
|
||||||
case _AM_NONE:
|
perror ("ioctl()");
|
||||||
vcd_error ("no way to read mode2");
|
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
/* exit (EXIT_FAILURE); */
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode2_form2)
|
||||||
|
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
{
|
memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE);
|
||||||
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;
|
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
|
static uint32_t
|
||||||
_cdio_stat_size (void *user_data)
|
_cdio_stat_size (void *user_data)
|
||||||
{
|
{
|
||||||
_img_private_t *_obj = user_data;
|
_img_private_t *_obj = user_data;
|
||||||
|
|
||||||
struct scsi_user_cdb suc;
|
struct cdrom_tocentry tocent;
|
||||||
uint8_t buf[12] = { 0, };
|
uint32_t size;
|
||||||
|
|
||||||
uint32_t retval;
|
tocent.cdte_track = CDROM_LEADOUT;
|
||||||
|
tocent.cdte_format = CDROM_LBA;
|
||||||
_cdio_init(_obj);
|
if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1)
|
||||||
|
{
|
||||||
memset (&suc, 0, sizeof (struct scsi_user_cdb));
|
perror ("ioctl(CDROMREADTOCENTRY)");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
size = tocent.cdte_addr.lba;
|
||||||
Return a string containing the default VCD device if none is specified.
|
|
||||||
*/
|
return size;
|
||||||
static char *
|
|
||||||
_cdio_get_default_device()
|
|
||||||
{
|
|
||||||
return strdup(DEFAULT_CDIO_DEVICE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -373,10 +249,8 @@ _cdio_set_arg (void *user_data, const char key[], const char value[])
|
|||||||
}
|
}
|
||||||
else if (!strcmp (key, "access-mode"))
|
else if (!strcmp (key, "access-mode"))
|
||||||
{
|
{
|
||||||
if (!strcmp(value, "READ_CD"))
|
if (!strcmp(value, "IOCTL"))
|
||||||
_obj->access_mode = _AM_READ_CD;
|
_obj->access_mode = _AM_IOCTL;
|
||||||
else if (!strcmp(value, "READ_10"))
|
|
||||||
_obj->access_mode = _AM_READ_10;
|
|
||||||
else
|
else
|
||||||
cdio_error ("unknown access type: %s. ignored.", value);
|
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;
|
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 */
|
#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 *
|
||||||
cdio_open_bsdi (const char *source_name)
|
cdio_open_bsdi (const char *source_name)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef HAVE_BSDI_CDROM
|
#ifdef HAVE_BSDI_CDROM
|
||||||
|
CdIo *ret;
|
||||||
_img_private_t *_data;
|
_img_private_t *_data;
|
||||||
|
|
||||||
cdio_funcs _funcs = {
|
cdio_funcs _funcs = {
|
||||||
@@ -400,13 +515,20 @@ cdio_open_bsdi (const char *source_name)
|
|||||||
.free = _cdio_free,
|
.free = _cdio_free,
|
||||||
.get_arg = _cdio_get_arg,
|
.get_arg = _cdio_get_arg,
|
||||||
.get_default_device = _cdio_get_default_device,
|
.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_sector = _read_mode2_sector,
|
||||||
|
.read_mode2_sectors = _read_mode2_sectors,
|
||||||
.set_arg = _cdio_set_arg,
|
.set_arg = _cdio_set_arg,
|
||||||
.stat_size = _cdio_stat_size
|
.stat_size = _cdio_stat_size
|
||||||
};
|
};
|
||||||
|
|
||||||
_data = _cdio_malloc (sizeof (_img_private_t));
|
_data = _cdio_malloc (sizeof (_img_private_t));
|
||||||
_data->access_mode = _AM_READ_CD;
|
_data->access_mode = _AM_IOCTL;
|
||||||
_data->init = false;
|
_data->init = false;
|
||||||
_data->fd = -1;
|
_data->fd = -1;
|
||||||
|
|
||||||
@@ -426,8 +548,8 @@ cdio_open_bsdi (const char *source_name)
|
|||||||
#else
|
#else
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif /* HAVE_BSDI_CDROM */
|
#endif /* HAVE_BSDI_CDROM */
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
cdio_have_bsdi (void)
|
cdio_have_bsdi (void)
|
||||||
|
|||||||
443
lib/_cdio_bsdi_old.c
Normal file
443
lib/_cdio_bsdi_old.c
Normal file
@@ -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 <hvr@gnu.org>
|
||||||
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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 </sys/dev/scsi/scsi.h>
|
||||||
|
#include </sys/dev/scsi/scsi_ioctl.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#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_assert.h"
|
||||||
#include "cdio_private.h"
|
#include "cdio_private.h"
|
||||||
@@ -209,7 +209,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
if (mode2_form2)
|
if (mode2_form2)
|
||||||
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE);
|
memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
110
lib/_cdio_generic.c
Normal file
110
lib/_cdio_generic.c
Normal file
@@ -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 <hvr@gnu.org>
|
||||||
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <linux/cdrom.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#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_assert.h"
|
||||||
#include "cdio_private.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)
|
#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
/* Things common to all drivers like this.
|
||||||
|
This must be first. */
|
||||||
int ioctls_debugged; /* for debugging */
|
generic_img_private_t gen;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_AM_NONE,
|
_AM_NONE,
|
||||||
@@ -76,9 +76,7 @@ typedef struct {
|
|||||||
_AM_READ_10
|
_AM_READ_10
|
||||||
} access_mode;
|
} access_mode;
|
||||||
|
|
||||||
char *source_name;
|
int ioctls_debugged; /* for debugging */
|
||||||
|
|
||||||
bool init;
|
|
||||||
|
|
||||||
/* Track information */
|
/* Track information */
|
||||||
bool toc_init; /* if true, info below is valid. */
|
bool toc_init; /* if true, info below is valid. */
|
||||||
@@ -93,41 +91,24 @@ typedef struct {
|
|||||||
static bool
|
static bool
|
||||||
_cdio_init (_img_private_t *_obj)
|
_cdio_init (_img_private_t *_obj)
|
||||||
{
|
{
|
||||||
if (_obj->init) {
|
if (_obj->gen.init) {
|
||||||
cdio_error ("init called more than once");
|
cdio_error ("init called more than once");
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_obj->init = true;
|
_obj->gen.init = true;
|
||||||
_obj->toc_init = false;
|
_obj->toc_init = false;
|
||||||
return true;
|
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
|
static int
|
||||||
_set_bsize (int fd, unsigned int bsize)
|
_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.
|
from lsn. Returns 0 if no error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
_cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
||||||
bool mode2_form2)
|
bool mode2_form2)
|
||||||
{
|
{
|
||||||
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
||||||
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
|
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
|
||||||
@@ -292,7 +273,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case _AM_IOCTL:
|
case _AM_IOCTL:
|
||||||
if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1)
|
if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1)
|
||||||
{
|
{
|
||||||
perror ("ioctl()");
|
perror ("ioctl()");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -302,7 +283,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
|
|
||||||
case _AM_READ_CD:
|
case _AM_READ_CD:
|
||||||
case _AM_READ_10:
|
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)))
|
(_obj->access_mode == _AM_READ_10)))
|
||||||
{
|
{
|
||||||
perror ("ioctl()");
|
perror ("ioctl()");
|
||||||
@@ -326,7 +307,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
if (mode2_form2)
|
if (mode2_form2)
|
||||||
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE);
|
memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -337,8 +318,8 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
Returns 0 if no error.
|
Returns 0 if no error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_read_mode2_sectors (void *user_data, void *data, lsn_t lsn,
|
_cdio_read_mode2_sectors (void *user_data, void *data, lsn_t lsn,
|
||||||
bool mode2_form2, unsigned nblocks)
|
bool mode2_form2, unsigned nblocks)
|
||||||
{
|
{
|
||||||
_img_private_t *_obj = user_data;
|
_img_private_t *_obj = user_data;
|
||||||
int i;
|
int i;
|
||||||
@@ -346,17 +327,18 @@ _read_mode2_sectors (void *user_data, void *data, lsn_t lsn,
|
|||||||
|
|
||||||
for (i = 0; i < nblocks; i++) {
|
for (i = 0; i < nblocks; i++) {
|
||||||
if (mode2_form2) {
|
if (mode2_form2) {
|
||||||
if ( (retval = _read_mode2_sector (_obj,
|
if ( (retval = _cdio_read_mode2_sector (_obj,
|
||||||
((char *)data) + (M2RAW_SECTOR_SIZE * i),
|
((char *)data)
|
||||||
lsn + i, true)) )
|
+ (M2RAW_SECTOR_SIZE * i),
|
||||||
|
lsn + i, true)) )
|
||||||
return retval;
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
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;
|
return retval;
|
||||||
|
|
||||||
memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8,
|
memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8,
|
||||||
M2F1_SECTOR_SIZE);
|
FORM1_DATA_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -375,7 +357,7 @@ _cdio_stat_size (void *user_data)
|
|||||||
|
|
||||||
tocent.cdte_track = CDROM_LEADOUT;
|
tocent.cdte_track = CDROM_LEADOUT;
|
||||||
tocent.cdte_format = CDROM_LBA;
|
tocent.cdte_format = CDROM_LBA;
|
||||||
if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1)
|
if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
|
||||||
{
|
{
|
||||||
perror ("ioctl(CDROMREADTOCENTRY)");
|
perror ("ioctl(CDROMREADTOCENTRY)");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
@@ -399,9 +381,9 @@ _cdio_set_arg (void *user_data, const char key[], const char value[])
|
|||||||
if (!value)
|
if (!value)
|
||||||
return -2;
|
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"))
|
else if (!strcmp (key, "access-mode"))
|
||||||
{
|
{
|
||||||
@@ -430,7 +412,7 @@ _cdio_read_toc (_img_private_t *_obj)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* read TOC header */
|
/* 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",
|
cdio_error("%s: %s\n",
|
||||||
"error in ioctl CDROMREADTOCHDR", strerror(errno));
|
"error in ioctl CDROMREADTOCHDR", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
@@ -440,7 +422,7 @@ _cdio_read_toc (_img_private_t *_obj)
|
|||||||
for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) {
|
for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) {
|
||||||
_obj->tocent[i-1].cdte_track = i;
|
_obj->tocent[i-1].cdte_track = i;
|
||||||
_obj->tocent[i-1].cdte_format = CDROM_MSF;
|
_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",
|
cdio_error("%s %d: %s\n",
|
||||||
"error in ioctl CDROMREADTOCENTRY for track",
|
"error in ioctl CDROMREADTOCENTRY for track",
|
||||||
i, strerror(errno));
|
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_track = CDROM_LEADOUT;
|
||||||
_obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF;
|
_obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF;
|
||||||
|
|
||||||
if (ioctl(_obj->fd, CDROMREADTOCENTRY,
|
if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY,
|
||||||
&_obj->tocent[TOTAL_TRACKS]) == -1 ) {
|
&_obj->tocent[TOTAL_TRACKS]) == -1 ) {
|
||||||
cdio_error("%s: %s\n",
|
cdio_error("%s: %s\n",
|
||||||
"error in ioctl CDROMREADTOCENTRY for lead-out",
|
"error in ioctl CDROMREADTOCENTRY for lead-out",
|
||||||
@@ -489,7 +471,7 @@ _cdio_eject_media (void *user_data) {
|
|||||||
int status;
|
int status;
|
||||||
int fd;
|
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) {
|
if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case CDS_TRAY_OPEN:
|
case CDS_TRAY_OPEN:
|
||||||
@@ -509,7 +491,7 @@ _cdio_eject_media (void *user_data) {
|
|||||||
ret=1;
|
ret=1;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
_cdio_free((void *) _obj);
|
cdio_generic_free((void *) _obj);
|
||||||
}
|
}
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@@ -523,7 +505,7 @@ _cdio_get_arg (void *user_data, const char key[])
|
|||||||
_img_private_t *_obj = user_data;
|
_img_private_t *_obj = user_data;
|
||||||
|
|
||||||
if (!strcmp (key, "source")) {
|
if (!strcmp (key, "source")) {
|
||||||
return _obj->source_name;
|
return _obj->gen.source_name;
|
||||||
} else if (!strcmp (key, "access-mode")) {
|
} else if (!strcmp (key, "access-mode")) {
|
||||||
switch (_obj->access_mode) {
|
switch (_obj->access_mode) {
|
||||||
case _AM_IOCTL:
|
case _AM_IOCTL:
|
||||||
@@ -676,7 +658,7 @@ cdio_open_linux (const char *source_name)
|
|||||||
|
|
||||||
cdio_funcs _funcs = {
|
cdio_funcs _funcs = {
|
||||||
.eject_media = _cdio_eject_media,
|
.eject_media = _cdio_eject_media,
|
||||||
.free = _cdio_free,
|
.free = cdio_generic_free,
|
||||||
.get_arg = _cdio_get_arg,
|
.get_arg = _cdio_get_arg,
|
||||||
.get_default_device = _cdio_get_default_device,
|
.get_default_device = _cdio_get_default_device,
|
||||||
.get_first_track_num= _cdio_get_first_track_num,
|
.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_green = _cdio_get_track_green,
|
||||||
.get_track_lba = NULL, /* This could be implemented if need be. */
|
.get_track_lba = NULL, /* This could be implemented if need be. */
|
||||||
.get_track_msf = _cdio_get_track_msf,
|
.get_track_msf = _cdio_get_track_msf,
|
||||||
.read_mode2_sector = _read_mode2_sector,
|
.lseek = cdio_generic_lseek,
|
||||||
.read_mode2_sectors = _read_mode2_sectors,
|
.read = cdio_generic_read,
|
||||||
|
.read_mode2_sector = _cdio_read_mode2_sector,
|
||||||
|
.read_mode2_sectors = _cdio_read_mode2_sectors,
|
||||||
.set_arg = _cdio_set_arg,
|
.set_arg = _cdio_set_arg,
|
||||||
.stat_size = _cdio_stat_size
|
.stat_size = _cdio_stat_size
|
||||||
};
|
};
|
||||||
|
|
||||||
_data = _cdio_malloc (sizeof (_img_private_t));
|
_data = _cdio_malloc (sizeof (_img_private_t));
|
||||||
_data->access_mode = _AM_READ_CD;
|
_data->access_mode = _AM_READ_CD;
|
||||||
_data->init = false;
|
_data->gen.init = false;
|
||||||
_data->fd = -1;
|
_data->gen.fd = -1;
|
||||||
|
|
||||||
_cdio_set_arg(_data, "source", (NULL == source_name)
|
_cdio_set_arg(_data, "source", (NULL == source_name)
|
||||||
? DEFAULT_CDIO_DEVICE: source_name);
|
? DEFAULT_CDIO_DEVICE: source_name);
|
||||||
@@ -705,7 +689,7 @@ cdio_open_linux (const char *source_name)
|
|||||||
if (_cdio_init(_data))
|
if (_cdio_init(_data))
|
||||||
return ret;
|
return ret;
|
||||||
else {
|
else {
|
||||||
_cdio_free (_data);
|
cdio_generic_free (_data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
135
lib/_cdio_nrg.c
135
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 <hvr@gnu.org>
|
Copyright (C) 2001,2003 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "_cdio_stdio.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 */
|
/* structures used */
|
||||||
|
|
||||||
@@ -102,9 +102,9 @@ typedef struct {
|
|||||||
int track_num; /* Probably is index+1 */
|
int track_num; /* Probably is index+1 */
|
||||||
msf_t start_msf;
|
msf_t start_msf;
|
||||||
int start_index;
|
int start_index;
|
||||||
int secsize; /* Number of sectors in track. Does not
|
int sec_count; /* Number of sectors in track. Does not
|
||||||
include pregap before next entry. */
|
include pregap before next entry. */
|
||||||
int flags; /* "DCP", "4CH", "PRE" */
|
int flags; /* "DCP", "4CH", "PRE" */
|
||||||
track_format_t track_format;
|
track_format_t track_format;
|
||||||
bool track_green;
|
bool track_green;
|
||||||
} track_info_t;
|
} track_info_t;
|
||||||
@@ -114,15 +114,15 @@ typedef struct {
|
|||||||
Possibly redundant with above track_info_t */
|
Possibly redundant with above track_info_t */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t start_lsn;
|
uint32_t start_lsn;
|
||||||
uint32_t secsize; /* Number of sectors in track. Does not
|
uint32_t sec_count; /* Number of sectors in track. Does not
|
||||||
include pregap before next entry. */
|
include pregap before next entry. */
|
||||||
uint64_t img_offset; /* Bytes offset from beginning of disk image file.*/
|
uint64_t img_offset; /* Bytes offset from beginning of disk image file.*/
|
||||||
} _mapping_t;
|
} _mapping_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool sector_2336_flag;
|
bool sector_2336_flag;
|
||||||
CdioDataSource *nrg_src;
|
CdioDataSource *data_source;
|
||||||
char *source_name;
|
char *source_name;
|
||||||
track_info_t tocent[100]; /* entry info for each track */
|
track_info_t tocent[100]; /* entry info for each track */
|
||||||
track_t total_tracks; /* number of tracks in image */
|
track_t total_tracks; /* number of tracks in image */
|
||||||
@@ -145,8 +145,8 @@ _cdio_free (void *user_data)
|
|||||||
|
|
||||||
free(_obj->source_name);
|
free(_obj->source_name);
|
||||||
|
|
||||||
if (_obj->nrg_src)
|
if (_obj->data_source)
|
||||||
cdio_stream_destroy (_obj->nrg_src);
|
cdio_stream_destroy (_obj->data_source);
|
||||||
|
|
||||||
_cdio_list_free (_obj->mapping, true);
|
_cdio_list_free (_obj->mapping, true);
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ _cdio_free (void *user_data)
|
|||||||
simulate ioctl(CDROMREADTOCENTRY).
|
simulate ioctl(CDROMREADTOCENTRY).
|
||||||
*/
|
*/
|
||||||
static void
|
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)
|
uint64_t img_offset, uint32_t blocksize)
|
||||||
{
|
{
|
||||||
const int track_num=_obj->total_tracks;
|
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 ();
|
_obj->mapping = _cdio_list_new ();
|
||||||
|
|
||||||
_cdio_list_append (_obj->mapping, _map);
|
_cdio_list_append (_obj->mapping, _map);
|
||||||
_map->start_lsn = start_lsn;
|
_map->start_lsn = start_lsn;
|
||||||
_map->secsize = secsize;
|
_map->sec_count = sec_count;
|
||||||
_map->img_offset = img_offset;
|
_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
|
/* Update _obj->tocent[track_num] and track_num These structures are
|
||||||
in a sense redundant witht the obj->mapping list. Perhaps one
|
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].track_num = track_num+1;
|
||||||
_obj->tocent[track_num].blocksize = blocksize;
|
_obj->tocent[track_num].blocksize = blocksize;
|
||||||
_obj->tocent[track_num].secsize = secsize;
|
_obj->tocent[track_num].sec_count = sec_count;
|
||||||
_obj->tocent[track_num].secsize = secsize;
|
|
||||||
|
|
||||||
_obj->total_tracks++;
|
_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;
|
_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)
|
if (_obj->size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size = cdio_stream_stat (_obj->nrg_src);
|
size = cdio_stream_stat (_obj->data_source);
|
||||||
|
|
||||||
{
|
{
|
||||||
PRAGMA_BEGIN_PACKED
|
PRAGMA_BEGIN_PACKED
|
||||||
@@ -232,8 +231,8 @@ PRAGMA_END_PACKED
|
|||||||
|
|
||||||
cdio_assert (sizeof (buf) == 12);
|
cdio_assert (sizeof (buf) == 12);
|
||||||
|
|
||||||
cdio_stream_seek (_obj->nrg_src, size - sizeof (buf));
|
cdio_stream_seek (_obj->data_source, size - sizeof (buf), SEEK_SET);
|
||||||
cdio_stream_read (_obj->nrg_src, (void *) &buf, sizeof (buf), 1);
|
cdio_stream_read (_obj->data_source, (void *) &buf, sizeof (buf), 1);
|
||||||
|
|
||||||
if (buf.v50.ID == UINT32_TO_BE (0x4e45524f)) /* "NERO" */
|
if (buf.v50.ID == UINT32_TO_BE (0x4e45524f)) /* "NERO" */
|
||||||
{
|
{
|
||||||
@@ -258,8 +257,8 @@ PRAGMA_END_PACKED
|
|||||||
|
|
||||||
footer_buf = _cdio_malloc (size - footer_start);
|
footer_buf = _cdio_malloc (size - footer_start);
|
||||||
|
|
||||||
cdio_stream_seek (_obj->nrg_src, footer_start);
|
cdio_stream_seek (_obj->data_source, footer_start, SEEK_SET);
|
||||||
cdio_stream_read (_obj->nrg_src, footer_buf, size - footer_start, 1);
|
cdio_stream_read (_obj->data_source, footer_buf, size - footer_start, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -487,7 +486,7 @@ _cdio_init (_img_private_t *_obj)
|
|||||||
return false;
|
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");
|
cdio_error ("init failed");
|
||||||
return false;
|
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
|
static uint32_t
|
||||||
_cdio_stat_size (void *user_data)
|
_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);
|
_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;
|
long img_offset = _map->img_offset;
|
||||||
int blocksize = _obj->sector_2336_flag
|
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;
|
img_offset += (lsn - _map->start_lsn) * blocksize;
|
||||||
|
|
||||||
cdio_stream_seek (_obj->nrg_src, img_offset);
|
cdio_stream_seek (_obj->data_source, img_offset, SEEK_SET);
|
||||||
cdio_stream_read (_obj->nrg_src,
|
cdio_stream_read (_obj->data_source,
|
||||||
_obj->sector_2336_flag ? (buf + 12 + 4) : buf,
|
_obj->sector_2336_flag ? (buf + 12 + 4) : buf,
|
||||||
blocksize, 1);
|
blocksize, 1);
|
||||||
|
|
||||||
@@ -547,7 +616,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn, bool form2)
|
|||||||
if (form2)
|
if (form2)
|
||||||
memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE);
|
memcpy (data, buf + 12 + 4, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
memcpy (data, buf + 12 + 4 + 8, M2F1_SECTOR_SIZE);
|
memcpy (data, buf + 12 + 4 + 8, FORM1_DATA_SIZE);
|
||||||
|
|
||||||
return 0;
|
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)) )
|
if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) )
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8,
|
memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8,
|
||||||
M2F1_SECTOR_SIZE);
|
FORM1_DATA_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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
|
Return the starting MSF (minutes/secs/frames) for the track number
|
||||||
track_num in obj. Tracks numbers start at 1.
|
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
|
static bool
|
||||||
_cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf)
|
_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_num_tracks = _cdio_get_num_tracks,
|
||||||
.get_track_format = _cdio_get_track_format,
|
.get_track_format = _cdio_get_track_format,
|
||||||
.get_track_green = _cdio_get_track_green,
|
.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,
|
.get_track_msf = _cdio_get_track_msf,
|
||||||
|
.lseek = _cdio_lseek,
|
||||||
|
.read = _cdio_read,
|
||||||
.read_mode2_sector = _read_mode2_sector,
|
.read_mode2_sector = _read_mode2_sector,
|
||||||
.read_mode2_sectors = _read_mode2_sectors,
|
.read_mode2_sectors = _read_mode2_sectors,
|
||||||
.set_arg = _cdio_set_arg,
|
.set_arg = _cdio_set_arg,
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "_cdio_stream.h"
|
#include "_cdio_stream.h"
|
||||||
#include "_cdio_stdio.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)
|
#define CDIO_STDIO_BUFSIZE (128*1024)
|
||||||
|
|
||||||
@@ -91,11 +91,11 @@ _stdio_free(void *user_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
_stdio_seek(void *user_data, long offset)
|
_stdio_seek(void *user_data, long offset, int whence)
|
||||||
{
|
{
|
||||||
_UserData *const ud = user_data;
|
_UserData *const ud = user_data;
|
||||||
|
|
||||||
if (fseek (ud->fd, offset, SEEK_SET))
|
if (fseek (ud->fd, offset, whence))
|
||||||
cdio_error ("fseek (): %s", strerror (errno));
|
cdio_error ("fseek (): %s", strerror (errno));
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "_cdio_stream.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
|
* DataSource implementations
|
||||||
@@ -66,7 +66,7 @@ _cdio_stream_open_if_necessary(CdioDataSource *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
cdio_stream_seek(CdioDataSource* obj, long offset)
|
cdio_stream_seek(CdioDataSource* obj, long offset, int whence)
|
||||||
{
|
{
|
||||||
cdio_assert (obj != NULL);
|
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);
|
cdio_warn("had to reposition DataSource from %ld to %ld!", obj->position, offset);
|
||||||
#endif
|
#endif
|
||||||
obj->position = offset;
|
obj->position = offset;
|
||||||
return obj->op.seek(obj->user_data, offset);
|
return obj->op.seek(obj->user_data, offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -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_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);
|
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);
|
cdio_stream_read(CdioDataSource* obj, void *ptr, long size, long nmemb);
|
||||||
|
|
||||||
long
|
long
|
||||||
cdio_stream_seek(CdioDataSource* obj, long offset);
|
cdio_stream_seek(CdioDataSource* obj, long offset, int whence);
|
||||||
|
|
||||||
long
|
long
|
||||||
cdio_stream_stat(CdioDataSource* obj);
|
cdio_stream_stat(CdioDataSource* obj);
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_SOLARIS_CDROM
|
#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 <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -62,9 +62,9 @@ static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.1 2003/03/24 19:01:09 rocky
|
|||||||
/* reader */
|
/* reader */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
/* Things common to all drivers like this.
|
||||||
|
This must be first. */
|
||||||
int ioctls_debugged; /* for debugging */
|
generic_img_private_t gen;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_AM_NONE,
|
_AM_NONE,
|
||||||
@@ -76,9 +76,8 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
} access_mode;
|
} access_mode;
|
||||||
|
|
||||||
char *source_name;
|
|
||||||
|
|
||||||
bool init;
|
int ioctls_debugged; /* for debugging */
|
||||||
|
|
||||||
/* Track information */
|
/* Track information */
|
||||||
bool toc_init; /* if true, info below is valid. */
|
bool toc_init; /* if true, info below is valid. */
|
||||||
@@ -96,9 +95,9 @@ _cdio_init (_img_private_t *_obj)
|
|||||||
|
|
||||||
struct dk_cinfo cinfo;
|
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));
|
cdio_error ("open (%s): %s", _obj->source_name, strerror (errno));
|
||||||
return false;
|
return false;
|
||||||
@@ -109,7 +108,7 @@ _cdio_init (_img_private_t *_obj)
|
|||||||
* Try to send MMC3 SCSI commands via the uscsi interface on
|
* Try to send MMC3 SCSI commands via the uscsi interface on
|
||||||
* ATAPI devices.
|
* ATAPI devices.
|
||||||
*/
|
*/
|
||||||
if ( ioctl(_obj->fd, DKIOCINFO, &cinfo) == 0
|
if ( ioctl(_obj->gen.fd, DKIOCINFO, &cinfo) == 0
|
||||||
&& ((strcmp(cinfo.dki_cname, "ide") == 0)
|
&& ((strcmp(cinfo.dki_cname, "ide") == 0)
|
||||||
|| (strncmp(cinfo.dki_cname, "pci", 3) == 0)) ) {
|
|| (strncmp(cinfo.dki_cname, "pci", 3) == 0)) ) {
|
||||||
_obj->access_mode = _AM_SUN_CTRL_ATAPI;
|
_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->access_mode = _AM_SUN_CTRL_SCSI;
|
||||||
}
|
}
|
||||||
|
|
||||||
_obj->init = true;
|
_obj->gen.init = true;
|
||||||
_obj->toc_init = false;
|
_obj->toc_init = false;
|
||||||
|
|
||||||
return true;
|
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.
|
Reads a single mode2 sector from cd device into data starting from lsn.
|
||||||
Returns 0 if no error.
|
Returns 0 if no error.
|
||||||
@@ -183,7 +164,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case _AM_SUN_CTRL_SCSI:
|
case _AM_SUN_CTRL_SCSI:
|
||||||
if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1) {
|
if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1) {
|
||||||
perror ("ioctl(..,CDROMREADMODE2,..)");
|
perror ("ioctl(..,CDROMREADMODE2,..)");
|
||||||
return 1;
|
return 1;
|
||||||
/* exit (EXIT_FAILURE); */
|
/* 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_buflen = M2RAW_SECTOR_SIZE;
|
||||||
sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ;
|
sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ;
|
||||||
sc.uscsi_timeout = 20;
|
sc.uscsi_timeout = 20;
|
||||||
if (ioctl(_obj->fd, USCSICMD, &sc)) {
|
if (ioctl(_obj->gen.fd, USCSICMD, &sc)) {
|
||||||
perror("USCSICMD: READ CD");
|
perror("USCSICMD: READ CD");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -252,7 +233,7 @@ _read_mode2_sector (void *user_data, void *data, lsn_t lsn,
|
|||||||
if (mode2_form2)
|
if (mode2_form2)
|
||||||
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
||||||
else
|
else
|
||||||
memcpy (((char *)data), buf + 8, M2F1_SECTOR_SIZE);
|
memcpy (((char *)data), buf + 8, FORM1_DATA_SIZE);
|
||||||
|
|
||||||
return 0;
|
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)) )
|
if ( (retval = _read_mode2_sector (_obj, buf, lsn + i, true)) )
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
memcpy (((char *)data) + (M2F1_SECTOR_SIZE * i), buf + 8,
|
memcpy (((char *)data) + (FORM1_DATA_SIZE * i), buf + 8,
|
||||||
M2F1_SECTOR_SIZE);
|
FORM1_DATA_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -301,7 +282,7 @@ _cdio_stat_size (void *user_data)
|
|||||||
|
|
||||||
tocent.cdte_track = CDROM_LEADOUT;
|
tocent.cdte_track = CDROM_LEADOUT;
|
||||||
tocent.cdte_format = CDROM_LBA;
|
tocent.cdte_format = CDROM_LBA;
|
||||||
if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1)
|
if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
|
||||||
{
|
{
|
||||||
perror ("ioctl(CDROMREADTOCENTRY)");
|
perror ("ioctl(CDROMREADTOCENTRY)");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
@@ -354,7 +335,7 @@ _cdio_read_toc (_img_private_t *_obj)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* read TOC header */
|
/* 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",
|
cdio_error("%s: %s\n",
|
||||||
"error in ioctl CDROMREADTOCHDR", strerror(errno));
|
"error in ioctl CDROMREADTOCHDR", strerror(errno));
|
||||||
return false;
|
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++) {
|
for (i=_obj->tochdr.cdth_trk0; i<=_obj->tochdr.cdth_trk1; i++) {
|
||||||
_obj->tocent[i-1].cdte_track = i;
|
_obj->tocent[i-1].cdte_track = i;
|
||||||
_obj->tocent[i-1].cdte_format = CDROM_MSF;
|
_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",
|
cdio_error("%s %d: %s\n",
|
||||||
"error in ioctl CDROMREADTOCENTRY for track",
|
"error in ioctl CDROMREADTOCENTRY for track",
|
||||||
i, strerror(errno));
|
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_track = CDROM_LEADOUT;
|
||||||
_obj->tocent[_obj->tochdr.cdth_trk1].cdte_format = CDROM_MSF;
|
_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 ) {
|
&_obj->tocent[_obj->tochdr.cdth_trk1]) == -1 ) {
|
||||||
cdio_error("%s: %s\n",
|
cdio_error("%s: %s\n",
|
||||||
"error in ioctl CDROMREADTOCENTRY for lead-out",
|
"error in ioctl CDROMREADTOCENTRY for lead-out",
|
||||||
@@ -397,13 +378,13 @@ _cdio_eject_media (void *user_data) {
|
|||||||
_img_private_t *_obj = user_data;
|
_img_private_t *_obj = user_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (_obj->fd > -1) {
|
if (_obj->gen.fd > -1) {
|
||||||
if ((ret = ioctl(_obj->fd, CDROMEJECT)) != 0) {
|
if ((ret = ioctl(_obj->gen.fd, CDROMEJECT)) != 0) {
|
||||||
_cdio_free((void *) _obj);
|
cdio_generic_free((void *) _obj);
|
||||||
cdio_error ("CDROMEJECT failed: %s\n", strerror(errno));
|
cdio_error ("CDROMEJECT failed: %s\n", strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
_cdio_free((void *) _obj);
|
cdio_generic_free((void *) _obj);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,7 +496,7 @@ _cdio_get_track_format(void *user_data, track_t track_num)
|
|||||||
{
|
{
|
||||||
_img_private_t *_obj = user_data;
|
_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 (!_obj->toc_init) _cdio_read_toc (_obj) ;
|
||||||
|
|
||||||
if (track_num > TOTAL_TRACKS || track_num == 0)
|
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;
|
_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 (!_obj->toc_init) _cdio_read_toc (_obj) ;
|
||||||
|
|
||||||
if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
|
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.
|
track_num in obj. Tracks numbers start at 1.
|
||||||
The "leadout" track is specified either by
|
The "leadout" track is specified either by
|
||||||
using track_num LEADOUT_TRACK or the total tracks+1.
|
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
|
static bool
|
||||||
_cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf)
|
_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 (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 (!_obj->toc_init) _cdio_read_toc (_obj) ;
|
||||||
|
|
||||||
if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
|
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 = {
|
cdio_funcs _funcs = {
|
||||||
.eject_media = _cdio_eject_media,
|
.eject_media = _cdio_eject_media,
|
||||||
.free = _cdio_free,
|
.free = cdio_generic_free,
|
||||||
.get_arg = _cdio_get_arg,
|
.get_arg = _cdio_get_arg,
|
||||||
.get_default_device = _cdio_get_default_device,
|
.get_default_device = _cdio_get_default_device,
|
||||||
.get_first_track_num= _cdio_get_first_track_num,
|
.get_first_track_num= _cdio_get_first_track_num,
|
||||||
.get_num_tracks = _cdio_get_num_tracks,
|
.get_num_tracks = _cdio_get_num_tracks,
|
||||||
.get_track_format = _cdio_get_track_format,
|
.get_track_format = _cdio_get_track_format,
|
||||||
.get_track_green = _cdio_get_track_green,
|
.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,
|
.get_track_msf = _cdio_get_track_msf,
|
||||||
|
.lseek = cdio_generic_lseek,
|
||||||
|
.read = cdio_generic_read,
|
||||||
.read_mode2_sector = _read_mode2_sector,
|
.read_mode2_sector = _read_mode2_sector,
|
||||||
.read_mode2_sectors = _read_mode2_sectors,
|
.read_mode2_sectors = _read_mode2_sectors,
|
||||||
.stat_size = _cdio_stat_size,
|
.stat_size = _cdio_stat_size,
|
||||||
@@ -636,7 +620,7 @@ cdio_open_solaris (const char *source_name)
|
|||||||
if (_cdio_init(_data))
|
if (_cdio_init(_data))
|
||||||
return ret;
|
return ret;
|
||||||
else {
|
else {
|
||||||
_cdio_free (_data);
|
cdio_generic_free (_data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
106
lib/cdio.c
106
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 <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "cdio_private.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] =
|
const char *track_format2str[5] =
|
||||||
@@ -41,11 +41,6 @@ const char *track_format2str[5] =
|
|||||||
|
|
||||||
CdIo_driver_t CdIo_driver[MAX_DRIVER] = { {0} };
|
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
|
/* The last valid entry of Cdio_driver. -1 means uninitialzed. -2
|
||||||
means some sort of error.
|
means some sort of error.
|
||||||
*/
|
*/
|
||||||
@@ -189,7 +184,7 @@ cdio_get_first_track_num (const CdIo *obj)
|
|||||||
track_t
|
track_t
|
||||||
cdio_get_num_tracks (const CdIo *obj)
|
cdio_get_num_tracks (const CdIo *obj)
|
||||||
{
|
{
|
||||||
cdio_assert (obj != NULL);
|
if (obj == NULL) return CDIO_INVALID_TRACK;
|
||||||
|
|
||||||
if (obj->op.get_num_tracks) {
|
if (obj->op.get_num_tracks) {
|
||||||
return obj->op.get_num_tracks (obj->user_data);
|
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
|
Return the starting MSF (minutes/secs/frames) for track number
|
||||||
track_num in obj. Track numbers start at 1.
|
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.
|
False is returned if there is no track entry.
|
||||||
*/
|
*/
|
||||||
bool
|
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);
|
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
|
bool
|
||||||
cdio_have_driver(driver_id_t driver_id)
|
cdio_have_driver(driver_id_t driver_id)
|
||||||
{
|
{
|
||||||
@@ -300,6 +334,9 @@ cdio_new (void *user_data, const cdio_funcs *funcs)
|
|||||||
return new_obj;
|
return new_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Free any resources associated with obj.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cdio_destroy (CdIo *obj)
|
cdio_destroy (CdIo *obj)
|
||||||
{
|
{
|
||||||
@@ -309,31 +346,46 @@ cdio_destroy (CdIo *obj)
|
|||||||
free (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
|
int
|
||||||
cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool mode2raw,
|
cdio_read_mode2_sectors (CdIo *obj, void *buf, lsn_t lsn, bool mode2raw,
|
||||||
unsigned num_sectors)
|
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 (obj != NULL);
|
||||||
cdio_assert (buf != NULL);
|
cdio_assert (buf != NULL);
|
||||||
cdio_assert (obj->op.read_mode2_sector != NULL
|
cdio_assert (obj->op.read_mode2_sectors != NULL);
|
||||||
|| obj->op.read_mode2_sectors != NULL);
|
|
||||||
|
|
||||||
if (obj->op.read_mode2_sectors)
|
return obj->op.read_mode2_sectors (obj->user_data, buf, lsn,
|
||||||
return obj->op.read_mode2_sectors (obj->user_data, buf, lsn,
|
mode2raw, num_sectors);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
46
lib/cdio.h
46
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 <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -25,6 +25,13 @@
|
|||||||
#ifndef __CDIO_H__
|
#ifndef __CDIO_H__
|
||||||
#define __CDIO_H__
|
#define __CDIO_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cdio_types.h"
|
#include "cdio_types.h"
|
||||||
#include "sector.h"
|
#include "sector.h"
|
||||||
|
|
||||||
@@ -79,6 +86,9 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
int cdio_eject_media (const CdIo *obj);
|
int cdio_eject_media (const CdIo *obj);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Free any resources associated with obj.
|
||||||
|
*/
|
||||||
void cdio_destroy (CdIo *obj);
|
void cdio_destroy (CdIo *obj);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -117,6 +127,15 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
bool cdio_get_track_green(const CdIo *obj, track_t track_num);
|
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
|
Return the starting MSF (minutes/secs/frames) for track number
|
||||||
track_num in obj. Track numbers start at 1.
|
track_num in obj. Track numbers start at 1.
|
||||||
@@ -124,7 +143,30 @@ extern "C" {
|
|||||||
using track_num LEADOUT_TRACK or the total tracks+1.
|
using track_num LEADOUT_TRACK or the total tracks+1.
|
||||||
False is returned if there is no track entry.
|
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
|
Reads a single mode2 sector from cd device into data starting
|
||||||
|
|||||||
@@ -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 <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
|
|
||||||
@@ -24,6 +24,13 @@
|
|||||||
#ifndef __CDIO_PRIVATE_H__
|
#ifndef __CDIO_PRIVATE_H__
|
||||||
#define __CDIO_PRIVATE_H__
|
#define __CDIO_PRIVATE_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cdio.h>
|
#include <cdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -66,13 +73,13 @@ extern "C" {
|
|||||||
track_t (*get_num_tracks) (void *user_data);
|
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.
|
track_num in obj. Tracks numbers start at 1.
|
||||||
The "leadout" track is specified either by
|
The "leadout" track is specified either by
|
||||||
using track_num LEADOUT_TRACK or the total tracks+1.
|
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.
|
Get format of track.
|
||||||
@@ -94,12 +101,26 @@ extern "C" {
|
|||||||
track_num in obj. Tracks numbers start at 1.
|
track_num in obj. Tracks numbers start at 1.
|
||||||
The "leadout" track is specified either by
|
The "leadout" track is specified either by
|
||||||
using track_num LEADOUT_TRACK or the total tracks+1.
|
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);
|
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.
|
from lsn. Returns 0 if no error.
|
||||||
*/
|
*/
|
||||||
int (*read_mode2_sector) (void *user_data, void *buf, lsn_t lsn,
|
int (*read_mode2_sector) (void *user_data, void *buf, lsn_t lsn,
|
||||||
@@ -125,6 +146,14 @@ extern "C" {
|
|||||||
|
|
||||||
} cdio_funcs;
|
} 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);
|
CdIo * cdio_new (void *user_data, const cdio_funcs *funcs);
|
||||||
|
|
||||||
/* The below structure describes a specific CD Input driver */
|
/* The below structure describes a specific CD Input driver */
|
||||||
@@ -151,6 +180,39 @@ extern "C" {
|
|||||||
on a particular host. */
|
on a particular host. */
|
||||||
extern CdIo_driver_t CdIo_all_drivers[MAX_DRIVER+1];
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -201,6 +201,11 @@ typedef uint8_t track_t;
|
|||||||
*/
|
*/
|
||||||
#define CDIO_INVALID_TRACK 0xFF
|
#define CDIO_INVALID_TRACK 0xFF
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constant for invalid LBA
|
||||||
|
*/
|
||||||
|
#define CDIO_INVALID_LBA 0xFFFFFFFF
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -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 <hvr@gnu.org>
|
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
* format sector type user data size (bytes)
|
* format sector type user data size (bytes)
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
* 1 (Red Book) CD-DA 2352 (CDDA_SECTOR_SIZE)
|
* 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)
|
* 3 (Yellow Book) Mode1 Form2 2336 (M2RAW_SECTOR_SIZE)
|
||||||
* 4 (Green Book) Mode2 Form1 2048 (M2F1_SECTOR_SIZE)
|
* 4 (Green Book) Mode2 Form1 2048 (M2F1_SECTOR_SIZE)
|
||||||
* 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
|
* 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
|
||||||
@@ -71,7 +71,9 @@
|
|||||||
|
|
||||||
#define CD_RAW_SECTOR_SIZE 2352
|
#define CD_RAW_SECTOR_SIZE 2352
|
||||||
#define CDDA_SECTOR_SIZE CD_RAW_SECTOR_SIZE
|
#define CDDA_SECTOR_SIZE CD_RAW_SECTOR_SIZE
|
||||||
|
#define M1F1_SECTOR_SIZE 2048
|
||||||
#define M2F1_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 M2F2_SECTOR_SIZE 2324
|
||||||
#define M2SUB_SECTOR_SIZE 2332
|
#define M2SUB_SECTOR_SIZE 2332
|
||||||
#define M2RAW_SECTOR_SIZE 2336
|
#define M2RAW_SECTOR_SIZE 2336
|
||||||
|
|||||||
@@ -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 <rocky@panix.com>
|
# Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
#
|
#
|
||||||
@@ -25,8 +25,14 @@ cdinfo_linux_SOURCES = cdinfo-linux.c
|
|||||||
cdinfo_linux_LDADD = $(LIBCDIO_LIBS) -lpopt
|
cdinfo_linux_LDADD = $(LIBCDIO_LIBS) -lpopt
|
||||||
else
|
else
|
||||||
EXTRA_DIST = cdinfo-linux.c
|
EXTRA_DIST = cdinfo-linux.c
|
||||||
|
if BUILD_CDIOTEST
|
||||||
|
bin_PROGRAMS = cdinfo cdiotest
|
||||||
|
cdiotest_SOURCES = cdiotest.c
|
||||||
|
cdiotest_LDADD = $(LIBCDIO_LIBS)
|
||||||
|
else
|
||||||
bin_PROGRAMS = cdinfo
|
bin_PROGRAMS = cdinfo
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
|
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
|
||||||
|
|
||||||
|
|||||||
40
src/cdinfo.c
40
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 <rocky@panix.com>
|
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
|
||||||
Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org>
|
Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org>
|
||||||
@@ -408,13 +408,24 @@ PARTICULAR PURPOSE.\n\
|
|||||||
/* some ISO 9660 fiddling */
|
/* some ISO 9660 fiddling */
|
||||||
|
|
||||||
static int
|
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);
|
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);
|
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 -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -479,11 +490,11 @@ get_joliet_level( void )
|
|||||||
if (is_it(sig)) printf("%s, ", sigs[sig].description)
|
if (is_it(sig)) printf("%s, ", sigs[sig].description)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
guess_filesystem(int start_session, bool is_green)
|
guess_filesystem(int start_session, track_t track_num)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
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;
|
return FS_UNKNOWN;
|
||||||
|
|
||||||
if (opts.debug_level > 0) {
|
if (opts.debug_level > 0) {
|
||||||
@@ -504,7 +515,7 @@ guess_filesystem(int start_session, bool is_green)
|
|||||||
return FS_INTERACTIVE;
|
return FS_INTERACTIVE;
|
||||||
} else { /* read sector 0 ONLY, when NO greenbook CD-I !!!! */
|
} 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;
|
return ret;
|
||||||
|
|
||||||
if (opts.debug_level > 0) {
|
if (opts.debug_level > 0) {
|
||||||
@@ -532,7 +543,7 @@ guess_filesystem(int start_session, bool is_green)
|
|||||||
ret |= ROCKRIDGE;
|
ret |= ROCKRIDGE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (read_block(BOOT_SECTOR, start_session, 3, true) < 0)
|
if (read_block(BOOT_SECTOR, start_session, 3, track_num) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (opts.debug_level > 0) {
|
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_CD_RTOS) &&
|
||||||
!is_it(IS_PHOTO_CD)) {
|
!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;
|
return ret;
|
||||||
|
|
||||||
if (opts.debug_level > 0) {
|
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_it(IS_EXT2)) ret |= FS_EXT2;
|
||||||
else if (is_3do()) ret |= FS_3DO;
|
else if (is_3do()) ret |= FS_3DO;
|
||||||
else {
|
else {
|
||||||
|
if (read_block(UFS_SUPERBLOCK_SECTOR, start_session, 2, track_num) < 0)
|
||||||
if (read_block(UFS_SUPERBLOCK_SECTOR, start_session, 2, true) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (opts.debug_level > 0) {
|
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 */
|
/* CD-I/Ready says start_track <= 30*75 then CDDA */
|
||||||
if (start_track > 100 /* 100 is just a guess */) {
|
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)
|
if ((fs & FS_MASK) != FS_UNKNOWN)
|
||||||
fs |= HIDDEN_TRACK;
|
fs |= HIDDEN_TRACK;
|
||||||
else {
|
else {
|
||||||
fs &= ~FS_MASK; /* del filesystem info */
|
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);
|
print_analysis(fs, num_audio);
|
||||||
@@ -971,7 +983,7 @@ main(int argc, const char *argv[])
|
|||||||
if (start_track < data_start + isofs_size)
|
if (start_track < data_start + isofs_size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fs = guess_filesystem(start_track, cdio_get_track_green(img, i));
|
fs = guess_filesystem(start_track, i);
|
||||||
|
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
/* track is beyond last session -> new session found */
|
/* track is beyond last session -> new session found */
|
||||||
|
|||||||
@@ -14,4 +14,4 @@ CD-ROM with CD-RTOS and ISO 9660 filesystem
|
|||||||
ISO 9660: 1101 blocks, label `MONVOISIN '
|
ISO 9660: 1101 blocks, label `MONVOISIN '
|
||||||
XA sectors Video CD
|
XA sectors Video CD
|
||||||
session #2 starts at track 2, LSN: 1251, ISO 9660 blocks: 1101
|
session #2 starts at track 2, LSN: 1251, ISO 9660 blocks: 1101
|
||||||
ISO 9660: 1101 blocks, label `'
|
ISO 9660: 1101 blocks, label `<EFBFBD><EFBFBD>)*<2A>c]<5D>d<1C><>q^\MvKM<4B><4D>b<EFBFBD><18><>Ǎ<10>%<25>'
|
||||||
|
|||||||
Reference in New Issue
Block a user