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:
rocky
2003-03-29 17:32:00 +00:00
parent 2e4f7d22ac
commit f488280282
21 changed files with 1572 additions and 538 deletions

View File

@@ -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

View File

@@ -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 \

View File

@@ -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>
@@ -51,7 +51,10 @@ 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;
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; seen_first_index_for_track=true;
} }
_obj->tocent[_obj->total_tracks-1].num_indices++;
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->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,

View File

@@ -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 (_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++;
if (form2)
{
retry:
switch (_obj->access_mode) switch (_obj->access_mode)
{ {
case _AM_NONE: case _AM_NONE:
vcd_error ("no way to read mode2"); cdio_error ("no way to read mode2");
return 1; return 1;
break; break;
case _AM_READ_CD: case _AM_IOCTL:
case _AM_READ_10: if (ioctl (_obj->fd, CDROMREADMODE2, &buf) == -1)
if (_read_mode2 (_obj->fd, data, lsn, 1,
(_obj->access_mode == _AM_READ_10)))
{ {
if (_obj->access_mode == _AM_READ_CD) perror ("ioctl()");
{
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; return 1;
/* exit (EXIT_FAILURE); */
} }
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;
_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;
tocent.cdte_track = CDROM_LEADOUT;
tocent.cdte_format = CDROM_LBA;
if (ioctl (_obj->fd, CDROMREADTOCENTRY, &tocent) == -1)
{ {
int i; perror ("ioctl(CDROMREADTOCENTRY)");
exit (EXIT_FAILURE);
retval = 0;
for (i = 8; i < 12; i++)
{
retval <<= 8;
retval += buf[i];
}
} }
return retval; size = tocent.cdte_addr.lba;
}
/*! return size;
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);
} }
/*! /*!
@@ -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
View 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 */
}

View File

@@ -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
View 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;
}

View File

@@ -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,7 +235,7 @@ _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, };
@@ -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,7 +318,7 @@ _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;
@@ -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)
+ (M2RAW_SECTOR_SIZE * i),
lsn + i, true)) ) 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;
} }

View File

@@ -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,7 +102,7 @@ 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;
@@ -114,7 +114,7 @@ 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;
@@ -122,7 +122,7 @@ typedef struct {
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;
@@ -168,10 +168,10 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t secsize,
_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,

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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;
} }
/*! /*!

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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>'