apply patches

This commit is contained in:
openKylinBot 2022-05-13 20:05:33 +08:00
commit 1a17599fcc
18 changed files with 3858 additions and 4292 deletions

View File

@ -32,10 +32,10 @@ export VERSION
ifeq ($(STATIC),TRUE)
LIBS = interface/libcdda_interface.a paranoia/libcdda_paranoia.a \
-static -lm -lrt
-static -lm -lrt @LIBCAM@
LIBDEP = interface/libcdda_interface.a paranoia/libcdda_paranoia.a
else
LIBS = -lcdda_interface -lcdda_paranoia -lm -lrt
LIBS = -lcdda_interface -lcdda_paranoia -lm -lrt @LIBCAM@
LIBDEP = interface/libcdda_interface.so paranoia/libcdda_paranoia.so
endif

View File

@ -1,16 +1,17 @@
.TH CDPARANOIA 1 "11 Sep 2008"
.SH NAME
cdparanoia 10.2 (Paranoia release III) \- an audio CD reading utility which includes extra data verification features
cdparanoia \- an audio CD reading utility which includes extra data verification features
.SH SYNOPSIS
.B cdparanoia
.RB [ options ]
.B span
.RB [ outfile ]
.RB | \-B
.SH DESCRIPTION
.B cdparanoia
retrieves audio tracks from CDDA capable CDROM drives. The data can
retrieves audio tracks from CDDA-capable CDROM drives. The data can
be saved to a file or directed to standard output in WAV, AIFF, AIFF-C
or raw format. Most ATAPI, SCSI and several proprietary CDROM drive
or raw format. Most ATAPI and SCSI and several proprietary CDROM drive
makes are supported;
.B cdparanoia
can determine if the target drive is CDDA capable.
@ -24,12 +25,12 @@ and scratch reconstruction capability.
.TP
.B \-A --analyze-drive
Run and log a complete analysis of drive caching, timing and reading behavior;
verifies that cdparanoia is correctly modelling a sprcific drive's cache and
verifies that cdparanoia is correctly modelling a specific drive's cache and
read behavior. Implies -vQL.
.TP
.B \-v --verbose
Be absurdly verbose about the autosensing and reading process. Good
Be absurdly verbose about the auto-sensing and reading process. Good
for setup and debugging.
.TP
@ -46,7 +47,7 @@ Save result summary to file, default filename cdparanoia.log.
.TP
.B \-L --log-debug [file]
Save detailed device autosense and debugging output to a file, default filename cdparanoia.log.
Save detailed device auto-sense and debugging output to a file, default filename cdparanoia.log.
.TP
.B \-V --version
@ -54,12 +55,12 @@ Print the program version and quit.
.TP
.B \-Q --query
Perform CDROM drive autosense, query and print the CDROM table of
Perform CDROM drive auto-sense, query and print the CDROM table of
contents, then quit.
.TP
.B \-s --search-for-drive
Forces a complete search for a cdrom drive, even if the /dev/cdrom link exists.
Forces a complete search for a CDROM drive, even if the /dev/cdrom link exists.
.TP
.B \-h --help
@ -69,7 +70,7 @@ usage and options.
.TP
.B \-p --output-raw
Output headerless data as raw 16 bit PCM data with interleaved samples in host byte order. To force little or big endian byte order, use
Output headerless data as raw 16-bit PCM data with interleaved samples in host byte order. To force little or big endian byte order, use
.B \-r
or
.B \-R
@ -77,40 +78,46 @@ as described below.
.TP
.B \-r --output-raw-little-endian
Output headerless data as raw 16 bit PCM data with interleaved samples in LSB first byte order.
Output headerless data as raw 16-bit PCM data with interleaved samples in LSB first byte order.
.TP
.B \-R --output-raw-big-endian
Output headerless data as raw 16 bit PCM data with interleaved samples in MSB first byte order.
Output headerless data as raw 16-bit PCM data with interleaved samples in MSB first byte order.
.TP
.B \-w --output-wav
Output data in Micro$oft RIFF WAV format (note that WAV data is always
LSB first byte order).
LSB-first byte order).
.TP
.B \-f --output-aiff
Output data in Apple AIFF format (note that AIFC data is
always in MSB first byte order).
always in MSB-first byte order).
.TP
.B \-a --output-aifc
Output data in uncompressed Apple AIFF-C format (note that AIFF-C data is
always in MSB first byte order).
always in MSB-first byte order).
.TP
.BI "\-B --batch "
Cdda2wav-style batch output flag; cdparanoia will split the output
Cdda2wav-style batch output flag;
.B cdparanoia
will split the output
into multiple files at track boundaries. Output file names are
prepended with 'track#.'
.TP
.B \-c --force-cdrom-little-endian
Some CDROM drives misreport their endianness (or do not report it at
all); it's possible that cdparanoia will guess wrong. Use
all); it's possible that
.B cdparanoia
will guess wrong. Use
.B \-c
to force cdparanoia to treat the drive as a little endian device.
to force
.B cdparanoia
to treat the drive as a little endian device.
.TP
.B \-C --force-cdrom-big-endian
@ -122,7 +129,7 @@ Force the interface backend to do atomic reads of
.B n
sectors per read. This number can be misleading; the kernel will often
split read requests into multiple atomic reads (the automated Paranoia
code is aware of this) or allow reads only wihin a restricted size
code is aware of this) or allow reads only within a restricted size
range.
.B This option should generally not be used.
@ -131,13 +138,13 @@ range.
Force the interface backend to read from
.B device
rather than the first readable CDROM drive it finds. This can be used
to specify devices of any valid interface type (ATAPI, SCSI or
to specify devices of any valid interface type (ATAPI, SCSI, or
proprietary).
.TP
.BI "\-k --force-cooked-device " device
This option forces use of the old 'cooked ioctl' kernel
interface with the specified cdrom device. The cooked ioctl interface
interface with the specified CDROM device. The cooked ioctl interface
is obsolete in Linux 2.6 if it is present at all.
.B \-k
cannot be used
@ -149,22 +156,22 @@ or
.TP
.BI "\-g --force-generic-device " device
This option forces use of the old 'generic scsi' (sg) kernel
interface with the specified generic scsi device.
This option forces use of the old 'generic SCSI' (sg) kernel
interface with the specified generic SCSI device.
.B \-g
cannot be used with
.BR \-k .
.B \-g
may be used with
.B \-d
to explicitly set both the SCSI cdrom and
generic (sg) devices seperately. This option is only useful on
obsolete SCSI setups and when using the generic scsi (sg) driver.
to explicitly set both the SCSI carom and
generic (sg) devices separately. This option is only useful on
obsolete SCSI setups and when using the generic SCSI (sg) driver.
.TP
.BI "\-S --force-read-speed " number
Use this option explicitly to set the read rate of the CD drive (where
supported). This can reduce underruns on machines with slow disks, or
supported). This can reduce underruns on machines that have slow disks, or
which are low on memory.
.TP
@ -184,16 +191,19 @@ every track seeming to start too late (losing a bit of the beginning
and catching a bit of the next track).
.B \-T
accounts for this behavior. Note that this option will cause
cdparanoia to attempt to read sectors before or past the known user
.B cdparanoia
to attempt to read sectors before or past the known user
data area of the disc, resulting in read errors at disc edges on most
drives and possibly even hard lockups on some buggy hardware.
.TP
.BI "\-O --sample-offset " number
Use this option to force the entire disc to shift sample position
output by the given amount; This can be used to shift track boundaries
output by the given amount; this can be used to shift track boundaries
for the whole disc manually on sample granularity. Note that this will
cause cdparanoia to attempt to read partial sectors before or past the
cause
.B cdparanoia
to attempt to read partial sectors before or past the
known user data area of the disc, probably causing read errors on most
drives and possibly even hard lockups on some buggy hardware.
@ -202,8 +212,11 @@ drives and possibly even hard lockups on some buggy hardware.
.B \-Z --disable-paranoia
Disable
.B all
data verification and correction features. When using -Z, cdparanoia
reads data exactly as would cdda2wav with an overlap setting of zero.
data verification and correction features. When using -Z,
.B cdparanoia
reads data exactly as would
.BR cdda2wav (1)
with an overlap setting of zero.
This option implies that
.B \-Y
is active.
@ -211,7 +224,9 @@ is active.
.TP
.B \-z --never-skip[=max_retries]
Do not accept any skips; retry forever if needed. An optional maximum
number of retries can be specified; for comparison, default without -z is
number of retries can be specified; for comparison, default without
.B -z
is
currently 20.
.TP
@ -221,7 +236,7 @@ boundaries is performed. It can wedge if errors occur in the attempted overlap a
.TP
.B \-X --abort-on-skip
If the read skips due to imperfect data, a scratch, whatever, abort reading this track. If output is to a file, delete the partially completed file.
If the read skips due to imperfect data, a scratch, or whatever, abort reading this track. If output is to a file, delete the partially completed file.
.SH OUTPUT SMILIES
.TP
@ -282,7 +297,9 @@ Unreported loss of streaming/other error in read
.B
!
Errors found after stage 1 correction; the drive is making the
same error through multiple re-reads, and cdparanoia is having trouble
same error through multiple re-reads, and
.B cdparanoia
is having trouble
detecting them.
.TP
.B
@ -295,8 +312,9 @@ Uncorrected error/skip
.SH SPAN ARGUMENT
The span argument specifies which track, tracks or subsections of
tracks to read. This argument is required.
The span argument specifies which track, tracks, or subsections of
tracks to read. This argument is required,
unless batch-mode is used (in batch-mode, cdparanoia will rip all tracks if no span is given).
.B NOTE:
Unless the span is a simple number, it's generally a good idea to
quote the span argument to protect it from the shell.
@ -307,7 +325,7 @@ specification. The syntax of an offset/span takes the rough form:
1[ww:xx:yy.zz]-2[aa:bb:cc.dd]
.P
Here, 1 and 2 are track numbers; the numbers in brackets provide a
finer grained offset within a particular track. [aa:bb:cc.dd] is in
finer-grained offset within a particular track. [aa:bb:cc.dd] is in
hours/minutes/seconds/sectors format. Zero fields need not be
specified: [::20], [:20], [20], [20.], etc, would be interpreted as
twenty seconds, [10:] would be ten minutes, [.30] would be thirty
@ -315,7 +333,7 @@ sectors (75 sectors per second).
.P
When only a single offset is supplied, it is interpreted as a starting
offset and ripping will continue to the end of the track. If a single
offset is preceeded or followed by a hyphen, the implicit missing
offset is preceded or followed by a hyphen, the implicit missing
offset is taken to be the start or end of the disc, respectively. Thus:
.TP
@ -335,18 +353,18 @@ Specifies ripping from the beginning of the disc up to 2:[30.35]
.B 2-4
Specifies ripping from the beginning of track 2 to the end of track 4.
.P
Again, don't forget to protect square brackets and preceeding hyphens from
Again, don't forget to protect square brackets from
the shell.
.SH EXAMPLES
A few examples, protected from the shell:
.TP
Query only with exhaustive search for a drive and full reporting of autosense:
Query only with exhaustive search for a drive and full reporting of auto-sense:
.P
cdparanoia -vsQ
.TP
Extract an entire disc, putting each track in a seperate file:
Extract an entire disc, putting each track in a separate file:
.P
cdparanoia -B
.TP
@ -354,26 +372,30 @@ Extract from track 1, time 0:30.12 to 1:10.00:
.P
cdparanoia "1[:30.12]-1[1:10]"
.TP
Extract from the beginning of the disc up to track 3:
Extract from the beginning of the disc up through track 3:
.P
cdparanoia -- "-3"
cdparanoia -- -3
.TP
The "--" above is to distinguish "-3" from an option flag.
.SH OUTPUT
The output file argument is optional; if it is not specified,
cdparanoia will output samples to one of
.B cdparanoia
will output samples to one of
.BR cdda.wav ", " cdda.aifc ", or " cdda.raw
depending on whether
.BR \-w ", " \-a ", " \-r " or " \-R " is used (" \-w
.BR \-w ", " \-a ", " \-r " or, " \-R " is used (" \-w
is the implicit default). The output file argument of
.B \-
specifies standard output; all data formats may be piped.
.SH ACKNOWLEDGEMENTS
Cdparanoia sprang from and once drew heavily from the interface of
.B cdparanoia
sprang from and once drew heavily from the interface of
Heiko Eissfeldt's (heiko@colossus.escape.de) 'cdda2wav'
package. Cdparanoia would not have happened without it.
package.
.B cdparanoia
would not have happened without it.
.P
Joerg Schilling has also contributed SCSI expertise through his
generic SCSI transport library.
@ -381,5 +403,6 @@ generic SCSI transport library.
.SH AUTHOR
Monty <monty@xiph.org>
.P
Cdparanoia's homepage may be found at:
.B cdparanoia's
homepage may be found at:
http://www.xiph.org/paranoia/

View File

@ -151,7 +151,7 @@ CD
.TP
.B \-Z --disable-paranoia
データ照合と訂正機能を
.b 全て
.B 全て
無効にします。-Z オプションを用いると、cdparanoia は
オーバーラップの設定が 0 である cdda2wav と全く同じようにデータの
読み取りを行います。

7220
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,5 @@
AC_INIT(interface/interface.c)
cp $srcdir/configure.guess $srcdir/config.guess
cp $srcdir/configure.sub $srcdir/config.sub
AC_CANONICAL_HOST
if test -z "$CC"; then
@ -56,12 +53,14 @@ fi
AC_CHECK_HEADERS(linux/sbpcd.h, SBPCD_H="-DSBPCD_H='1' ")
AC_CHECK_HEADERS(linux/ucdrom.h, UCDROM_H="-DUCDROM_H='1' ")
AC_CHECK_HEADERS(cam/cam.h, LIBCAM="-lcam")
AC_PROG_MAKE_SET
AC_C_CONST
AC_SUBST(SBPCD_H)
AC_SUBST(UCDROM_H)
AC_SUBST(LIBCAM)
AC_SUBST(TYPESIZES)
AC_SUBST(OPT)
AC_SUBST(DEBUG)

View File

@ -15,7 +15,7 @@ LD=@CC@
LDFLAGS=@LDFLAGS@ $(FLAGS)
AR=@AR@
RANLIB=@RANLIB@
LIBS = -lm -lrt
LIBS = -lm -lrt @LIBCAM@
CPPFLAGS+=-D_REENTRANT
OFILES = scan_devices.o common_interface.o cooked_interface.o interface.o\

View File

@ -84,7 +84,7 @@ typedef struct cdrom_drive{
int is_atapi;
int is_mmc;
cdda_private_data_t *private;
cdda_private_data_t *private_data;
void *reserved;
unsigned char inqbytes[4];

View File

@ -13,15 +13,22 @@
#include "utils.h"
#include "smallft.h"
#if defined(__linux__)
#include <linux/hdreg.h>
#endif
/* Test for presence of a cdrom by pinging with the 'CDROMVOLREAD' ioctl() */
/* Also test using CDROM_GET_CAPABILITY (if available) as some newer DVDROMs will
reject CDROMVOLREAD ioctl for god-knows-what reason */
int ioctl_ping_cdrom(int fd){
#if defined(__linux__)
struct cdrom_volctrl volctl;
if (ioctl(fd, CDROMVOLREAD, &volctl) &&
ioctl(fd, CDROM_GET_CAPABILITY, NULL)<0)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
struct ioc_vol volctl;
if (ioctl(fd, CDIOCGETVOL, &volctl))
#endif
return(1); /* failure */
return(0);
@ -29,6 +36,7 @@ int ioctl_ping_cdrom(int fd){
}
#if defined(__linux__)
/* Use the ioctl thingy above ping the cdrom; this will get model info */
char *atapi_drive_info(int fd){
/* Work around the fact that the struct grew without warning in
@ -49,6 +57,7 @@ char *atapi_drive_info(int fd){
free(id);
return(ret);
}
#endif
int data_bigendianp(cdrom_drive *d){
float lsb_votes=0;
@ -174,7 +183,9 @@ int data_bigendianp(cdrom_drive *d){
knows the leadout/leadin size. */
int FixupTOC(cdrom_drive *d,int tracks){
#if defined(__linux__)
struct cdrom_multisession ms_str;
#endif
int j;
/* First off, make sure the 'starting sector' is >=0 */
@ -211,6 +222,8 @@ int FixupTOC(cdrom_drive *d,int tracks){
/* For a scsi device, the ioctl must go to the specialized SCSI
CDROM device, not the generic device. */
/* XXX */
#if defined(__linux__)
if (d->ioctl_fd != -1) {
int result;
@ -235,6 +248,7 @@ int FixupTOC(cdrom_drive *d,int tracks){
return 1;
}
}
#endif
return 0;
}

View File

@ -1,6 +1,8 @@
/******************************************************************
* CopyPolicy: GNU Lesser General Public License 2.1 applies
* Copyright (C) Monty xiphmont@mit.edu
* FreeBSD porting (c) 2003
* Simon 'corecode' Schubert <corecode@corecode.ath.cx>
*
* CDROM code specific to the cooked ioctl interface
*
@ -13,17 +15,18 @@
static int timed_ioctl(cdrom_drive *d, int fd, int command, void *arg){
struct timespec tv1;
struct timespec tv2;
int ret1=clock_gettime(d->private->clock,&tv1);
int ret1=clock_gettime(d->private_data->clock,&tv1);
int ret2=ioctl(fd, command,arg);
int ret3=clock_gettime(d->private->clock,&tv2);
int ret3=clock_gettime(d->private_data->clock,&tv2);
if(ret1<0 || ret3<0){
d->private->last_milliseconds=-1;
d->private_data->last_milliseconds=-1;
}else{
d->private->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
d->private_data->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
}
return ret2;
}
#if defined(__linux__)
static int cooked_readtoc (cdrom_drive *d){
int i;
int tracks;
@ -157,6 +160,140 @@ static long cooked_read (cdrom_drive *d, void *p, long begin, long sectors){
return ret;
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int
cooked_readtoc(cdrom_drive *d)
{
int i;
struct ioc_toc_header hdr;
struct ioc_read_toc_single_entry entry;
if (ioctl(d->ioctl_fd, CDIOREADTOCHEADER, &hdr) == -1) {
int ret;
if (errno == EPERM) {
ret = -102;
cderror(d, "102: ");
} else {
ret = -4;
cderror(d, "004: Unable to read table of contents header: ");
}
cderror(d, strerror(errno));
cderror(d, "\n");
return ret;
}
entry.address_format = CD_LBA_FORMAT;
for (i = hdr.starting_track; i <= hdr.ending_track; ++i) {
entry.track = i;
if (ioctl(d->ioctl_fd, CDIOREADTOCENTRY, &entry) == -1) {
cderror(d, "005: Unable to read table of contents entry\n");
return -5;
}
d->disc_toc[i - hdr.starting_track].bFlags = entry.entry.control;
d->disc_toc[i - hdr.starting_track].bTrack = entry.entry.track;
d->disc_toc[i - hdr.starting_track].dwStartSector = be32_to_cpu(entry.entry.addr.lba);
}
entry.track = 0xaa; /* leadout */
if (ioctl(d->ioctl_fd, CDIOREADTOCENTRY, &entry) == -1) {
cderror(d, "005: Unable to read table of contents entry\n");
return -5;
}
d->disc_toc[i - hdr.starting_track].bFlags = entry.entry.control;
d->disc_toc[i - hdr.starting_track].bTrack = entry.entry.track;
d->disc_toc[i - hdr.starting_track].dwStartSector = be32_to_cpu(entry.entry.addr.lba);
d->cd_extra = FixupTOC(d, hdr.ending_track - hdr.starting_track + 2); /* with TOC */
return hdr.ending_track - hdr.starting_track + 1;
}
static int
cooked_setspeed(cdrom_drive *d, int speed)
{
#ifdef CDRIOCREADSPEED
speed *= 177;
return ioctl(d->ioctl_fd, CDRIOCREADSPEED, &speed);
#else
return -1;
#endif
}
static long
cooked_read(cdrom_drive *d, void *p, long begin, long sectors)
{
int retry_count = 0;
#ifndef CDIOCREADAUDIO
int bsize = CD_FRAMESIZE_RAW;
#else
struct ioc_read_audio arg;
if (sectors > d->nsectors)
sectors = d->nsectors;
arg.address_format = CD_LBA_FORMAT;
arg.address.lba = begin;
arg.buffer = p;
#endif
#ifndef CDIOCREADAUDIO
if (ioctl(d->ioctl_fd, CDRIOCSETBLOCKSIZE, &bsize) == -1)
return -7;
#endif
for (;;) {
#ifndef CDIOCREADAUDIO
if (pread(d->ioctl_fd, p, sectors*bsize, begin*bsize) != sectors*bsize) {
#else
arg.nframes = sectors;
if (ioctl(d->ioctl_fd, CDIOCREADAUDIO, &arg) == -1) {
#endif
if (!d->error_retry)
return -7;
switch (errno) {
case ENOMEM:
if (sectors == 1) {
cderror(d, "300: Kernel memory error\n");
return -300;
}
/* FALLTHROUGH */
default:
if (sectors == 1) {
if (retry_count > MAX_RETRIES - 1) {
char b[256];
snprintf(b, sizeof(b),
"010: Unable to access sector %ld; "
"skipping...\n", begin);
cderror(d, b);
return -10;
}
break;
}
}
if (retry_count > 4 && sectors > 1)
sectors = sectors * 3 / 4;
++retry_count;
if (retry_count > MAX_RETRIES) {
cderror(d, "007: Unknown, unrecoverable error reading data\n");
return -7;
}
} else
break;
}
return sectors;
}
#endif
/* hook */
static int Dummy (cdrom_drive *d,int Switch){
return(0);
@ -221,6 +358,7 @@ static void check_exceptions(cdrom_drive *d,exception *list){
int cooked_init_drive (cdrom_drive *d){
int ret;
#if defined(__linux__)
switch(d->drive_type){
case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
@ -271,6 +409,9 @@ int cooked_init_drive (cdrom_drive *d){
default:
d->nsectors=40;
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
d->nsectors = 26; /* FreeBSD only support 64K I/O transfer size */
#endif
d->enable_cdda = Dummy;
d->read_audio = cooked_read;
d->read_toc = cooked_readtoc;

View File

@ -39,9 +39,17 @@ int cdda_close(cdrom_drive *d){
if(d->drive_model)free(d->drive_model);
if(d->cdda_fd!=-1)close(d->cdda_fd);
if(d->ioctl_fd!=-1 && d->ioctl_fd!=d->cdda_fd)close(d->ioctl_fd);
if(d->private){
if(d->private->sg_hd)free(d->private->sg_hd);
free(d->private);
if(d->private_data){
#if defined(__linux__)
if(d->private_data->sg_hd)free(d->private_data->sg_hd);
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if(d->private_data->dev)
cam_close_device(d->private_data->dev);
if(d->private_data->ccb)
cam_freeccb(d->private_data->ccb);
if(d->private_data->sg_buffer)free(d->private_data->sg_buffer);
#endif
free(d->private_data);
}
free(d);
@ -118,7 +126,7 @@ long cdda_read_timed(cdrom_drive *d, void *buffer, long beginsector, long sector
if(d->bigendianp==-1) /* not determined yet */
d->bigendianp=data_bigendianp(d);
if(d->bigendianp!=bigendianp()){
if(buffer && d->bigendianp!=bigendianp()){
int i;
u_int16_t *p=(u_int16_t *)buffer;
long els=sectors*CD_FRAMESIZE_RAW/2;
@ -127,7 +135,7 @@ long cdda_read_timed(cdrom_drive *d, void *buffer, long beginsector, long sector
}
}
}
if(ms)*ms=d->private->last_milliseconds;
if(ms)*ms=d->private_data->last_milliseconds;
return(sectors);
}

View File

@ -26,6 +26,8 @@
#include <sys/time.h>
#include <sys/types.h>
#if defined(__linux__)
#include <linux/major.h>
#include <linux/version.h>
@ -54,7 +56,6 @@
#include <linux/cdrom.h>
#include <linux/major.h>
#include "cdda_interface.h"
#ifndef SG_EMULATED_HOST
/* old kernel version; the check for the ioctl is still runtime, this
@ -64,6 +65,19 @@
#define SG_GET_TRANSFORM 0x2205
#endif
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/cdio.h>
#include <sys/cdrio.h>
#include <cam/scsi/scsi_message.h>
#include <camlib.h>
#endif
#include "cdda_interface.h"
#ifndef SG_IO
/* old kernel version; the usage is all runtime-safe, this is just to
build */
@ -98,19 +112,30 @@ typedef struct sg_io_hdr
#endif
struct cdda_private_data {
#if defined(__linux__)
struct sg_header *sg_hd;
unsigned char *sg_buffer; /* points into sg_hd */
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
struct cam_device *dev;
#endif
unsigned char *sg_buffer; /* on Linux points into sg_hd */
clockid_t clock;
int last_milliseconds;
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
union ccb *ccb;
#endif
};
#define MAX_RETRIES 8
#define MAX_BIG_BUFF_SIZE 65536
#define MIN_BIG_BUFF_SIZE 4096
#define SG_OFF sizeof(struct sg_header)
extern int cooked_init_drive (cdrom_drive *d);
#if defined(__linux__)
extern unsigned char *scsi_inquiry (cdrom_drive *d);
#define SG_OFF sizeof(struct sg_header)
#else
#define SG_OFF (0)
#endif
extern int scsi_init_drive (cdrom_drive *d);
#ifdef CDDA_TEST
extern int test_init_drive (cdrom_drive *d);

View File

@ -24,6 +24,8 @@
#define MAX_DEV_LEN 20 /* Safe because strings only come from below */
/* must be absolute paths! */
#if defined(__linux__)
static char *scsi_cdrom_prefixes[]={
"/dev/scd",
"/dev/sr",
@ -52,6 +54,17 @@ static char *cdrom_devices[]={
"/dev/cm206cd",
"/dev/gscd",
"/dev/optcd",NULL};
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static char *cdrom_devices[] = {
"/dev/cd?",
"/dev/acd?",
"/dev/wcd?",
"/dev/mcd?",
"/dev/cd?c",
"/dev/acd?c",
"/dev/wcd?c",
"/dev/mcd?c", NULL};
#endif
/* Functions here look for a cdrom drive; full init of a drive type
happens in interface.c */
@ -78,10 +91,12 @@ cdrom_drive *cdda_find_a_cdrom(int messagedest,char **messages){
if((d=cdda_identify(buffer,messagedest,messages)))
return(d);
idmessage(messagedest,messages,"",NULL);
#if defined(__linux__)
buffer[pos-(cdrom_devices[i])]=j+97;
if((d=cdda_identify(buffer,messagedest,messages)))
return(d);
idmessage(messagedest,messages,"",NULL);
#endif
}
}else{
/* Name. Go for it. */
@ -145,6 +160,7 @@ char *test_resolve_symlink(const char *file,int messagedest,char **messages){
}
#if defined(__linux__)
cdrom_drive *cdda_identify_cooked(const char *dev, int messagedest,
char **messages){
@ -179,6 +195,12 @@ cdrom_drive *cdda_identify_cooked(const char *dev, int messagedest,
case IDE1_MAJOR:
case IDE2_MAJOR:
case IDE3_MAJOR:
case IDE4_MAJOR:
case IDE5_MAJOR:
case IDE6_MAJOR:
case IDE7_MAJOR:
case IDE8_MAJOR:
case IDE9_MAJOR:
/* Yay, ATAPI... */
/* Ping for CDROM-ness */
@ -264,16 +286,71 @@ cdrom_drive *cdda_identify_cooked(const char *dev, int messagedest,
d->interface=COOKED_IOCTL;
d->bigendianp=-1; /* We don't know yet... */
d->nsectors=-1;
d->private=calloc(1,sizeof(*d->private));
d->private_data=calloc(1,sizeof(*d->private_data));
{
/* goddamnit */
struct timespec tv;
d->private->clock=(clock_gettime(CLOCK_MONOTONIC,&tv)<0?CLOCK_REALTIME:CLOCK_MONOTONIC);
d->private_data->clock=(clock_gettime(CLOCK_MONOTONIC,&tv)<0?CLOCK_REALTIME:CLOCK_MONOTONIC);
}
idmessage(messagedest,messages,"\t\tCDROM sensed: %s\n",description);
return(d);
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
cdrom_drive *
cdda_identify_cooked(const char *dev, int messagedest, char **messages)
{
cdrom_drive *d;
struct stat st;
if (stat(dev, &st)) {
idperror(messagedest, messages, "\t\tCould not stat %s", dev);
return NULL;
}
if (!S_ISCHR(st.st_mode)) {
idmessage(messagedest, messages, "\t\t%s is no block device", dev);
return NULL;
}
if ((d = calloc(1, sizeof(*d))) == NULL) {
idperror(messagedest, messages, "\t\tCould not allocate memory", NULL);
return NULL;
}
d->ioctl_fd = -1;
if ((d->ioctl_fd = open(dev, O_RDONLY)) == -1) {
idperror(messagedest, messages, "\t\tCould not open %s", dev);
goto cdda_identify_cooked_fail;
}
if (ioctl_ping_cdrom(d->ioctl_fd)) {
idmessage(messagedest, messages, "\t\tDevice %s is not a CDROM", dev);
goto cdda_identify_cooked_fail;
}
d->cdda_device_name = copystring(dev);
d->drive_model = copystring("Generic cooked ioctl CDROM");
d->interface = COOKED_IOCTL;
d->bigendianp = -1;
d->nsectors = -1;
idmessage(messagedest, messages, "\t\tCDROM sensed: %s\n", d->drive_model);
return d;
cdda_identify_cooked_fail:
if (d != NULL) {
if (d->ioctl_fd != -1)
close(d->ioctl_fd);
free(d);
}
return NULL;
}
#endif
#if defined(__linux__)
struct sg_id {
long l1; /* target | lun << 8 | channel << 16 | low_ino << 24 */
long l2; /* Unique id */
@ -400,6 +477,7 @@ matchfail:
if(dev!=-1)close(dev);
return(NULL);
}
#endif
void strscat(char *a,char *b,int n){
int i;
@ -411,6 +489,7 @@ void strscat(char *a,char *b,int n){
strcat(a," ");
}
#if defined(__linux__)
/* At this point, we're going to punt compatability before SG2, and
allow only SG2 and SG3 */
static int verify_SG_version(cdrom_drive *d,int messagedest,
@ -674,15 +753,15 @@ cdrom_drive *cdda_identify_scsi(const char *generic_device,
d->bigendianp=-1; /* We don't know yet... */
d->nsectors=-1;
d->messagedest = messagedest;
d->private=calloc(1,sizeof(*d->private));
d->private_data=calloc(1,sizeof(*d->private_data));
{
/* goddamnit */
struct timespec tv;
d->private->clock=(clock_gettime(CLOCK_MONOTONIC,&tv)<0?CLOCK_REALTIME:CLOCK_MONOTONIC);
d->private_data->clock=(clock_gettime(CLOCK_MONOTONIC,&tv)<0?CLOCK_REALTIME:CLOCK_MONOTONIC);
}
if(use_sgio){
d->interface=SGIO_SCSI;
d->private->sg_buffer=(unsigned char *)(d->private->sg_hd=malloc(MAX_BIG_BUFF_SIZE));
d->private_data->sg_buffer=(unsigned char *)(d->private_data->sg_hd=malloc(MAX_BIG_BUFF_SIZE));
g_fd=d->cdda_fd=dup(d->ioctl_fd);
}else{
version=verify_SG_version(d,messagedest,messages);
@ -696,8 +775,8 @@ cdrom_drive *cdda_identify_scsi(const char *generic_device,
}
/* malloc our big buffer for scsi commands */
d->private->sg_hd=malloc(MAX_BIG_BUFF_SIZE);
d->private->sg_buffer=((unsigned char *)d->private->sg_hd)+SG_OFF;
d->private_data->sg_hd=malloc(MAX_BIG_BUFF_SIZE);
d->private_data->sg_buffer=((unsigned char *)d->private_data->sg_hd)+SG_OFF;
}
{
@ -772,14 +851,104 @@ cdda_identify_scsi_fail:
if(i_fd!=-1)close(i_fd);
if(g_fd!=-1)close(g_fd);
if(d){
if(d->private){
if(d->private->sg_hd)free(d->private->sg_hd);
free(d->private);
if(d->private_data){
if(d->private_data->sg_hd)free(d->private_data->sg_hd);
free(d->private_data);
}
free(d);
}
return(NULL);
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
cdrom_drive *cdda_identify_scsi(const char *dummy,
const char *device,
int messagedest,
char **messages)
{
char *devname;
cdrom_drive *d = NULL;
if (device == NULL) {
idperror(messagedest, messages, "\t\tNo device specified", NULL);
return NULL;
}
if ((devname = test_resolve_symlink(device, messagedest, messages)) == NULL)
return NULL;
if ((d = calloc(1, sizeof(*d))) == NULL) {
idperror(messagedest, messages, "\t\tCould not allocate memory", NULL);
free(devname);
return NULL;
}
if ((d->private_data = calloc(1, sizeof(*(d->private_data)))) == NULL) {
idperror(messagedest, messages, "\t\tCould not allocate memory", NULL);
free(d);
free(devname);
return NULL;
}
if ((d->private_data->dev = cam_open_device(devname, O_RDWR)) == NULL) {
idperror(messagedest, messages, "\t\tCould not open SCSI device: %s", cam_errbuf);
goto cdda_identify_scsi_fail;
}
if ((d->private_data->ccb = cam_getccb(d->private_data->dev)) == NULL) {
idperror(messagedest, messages, "\t\tCould not allocate ccb", NULL);
goto cdda_identify_scsi_fail;
}
if (strncmp(d->private_data->dev->inq_data.vendor, "TOSHIBA", 7) == 0 &&
strncmp(d->private_data->dev->inq_data.product, "CD_ROM", 6) == 0 &&
SID_TYPE(&d->private_data->dev->inq_data) == T_DIRECT) {
d->private_data->dev->inq_data.device = T_CDROM;
d->private_data->dev->inq_data.dev_qual2 |= 0x80;
}
if (SID_TYPE(&d->private_data->dev->inq_data) != T_CDROM &&
SID_TYPE(&d->private_data->dev->inq_data) != T_WORM) {
idmessage(messagedest, messages,
"\t\tDevice is neither a CDROM nor a WORM device\n", NULL);
goto cdda_identify_scsi_fail;
}
d->cdda_device_name = copystring(devname);
d->ioctl_fd = -1;
d->bigendianp = -1;
d->nsectors = -1;
d->lun = d->private_data->dev->target_lun;
d->interface = GENERIC_SCSI;
if ((d->private_data->sg_buffer = malloc(MAX_BIG_BUFF_SIZE)) == NULL) {
idperror(messagedest, messages, "Could not allocate buffer memory", NULL);
goto cdda_identify_scsi_fail;
}
if ((d->drive_model = calloc(36,1)) == NULL) {
}
strscat(d->drive_model, d->private_data->dev->inq_data.vendor, SID_VENDOR_SIZE);
strscat(d->drive_model, d->private_data->dev->inq_data.product, SID_PRODUCT_SIZE);
strscat(d->drive_model, d->private_data->dev->inq_data.revision, SID_REVISION_SIZE);
idmessage(messagedest, messages, "\nCDROM model sensed: %s", d->drive_model);
return d;
cdda_identify_scsi_fail:
free(devname);
if (d) {
if (d->private_data->ccb)
cam_freeccb(d->private_data->ccb);
if (d->private_data->dev)
cam_close_device(d->private_data->dev);
free(d);
}
return NULL;
}
#endif
#ifdef CDDA_TEST
@ -821,7 +990,7 @@ cdrom_drive *cdda_identify_test(const char *filename, int messagedest,
d->interface=TEST_INTERFACE;
d->bigendianp=-1; /* We don't know yet... */
d->nsectors=-1;
d->private=calloc(1,sizeof(*d->private));
d->private_data=calloc(1,sizeof(*d->private_data));
d->drive_model=copystring("File based test interface");
idmessage(messagedest,messages,"\t\tCDROM sensed: %s\n",d->drive_model);

View File

@ -12,16 +12,21 @@
#include "common_interface.h"
#include "utils.h"
#include <time.h>
#ifndef SG_MAX_SENSE
#define SG_MAX_SENSE 16
#endif
static int timed_ioctl(cdrom_drive *d, int fd, int command, void *arg){
struct timespec tv1;
struct timespec tv2;
int ret1=clock_gettime(d->private->clock,&tv1);
int ret1=clock_gettime(d->private_data->clock,&tv1);
int ret2=ioctl(fd, command,arg);
int ret3=clock_gettime(d->private->clock,&tv2);
int ret3=clock_gettime(d->private_data->clock,&tv2);
if(ret1<0 || ret3<0){
d->private->last_milliseconds=-1;
d->private_data->last_milliseconds=-1;
}else{
d->private->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
d->private_data->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000. + (tv2.tv_nsec-tv1.tv_nsec)/1000000.;
}
return ret2;
}
@ -36,6 +41,7 @@ static void tweak_SG_buffer(cdrom_drive *d) {
int table, reserved, cur, err;
char buffer[256];
#if defined(__linux__)
/* SG_SET_RESERVED_SIZE doesn't actually allocate or reserve anything.
* what it _does_ do is give you an error if you ask for a value
* larger than q->max_sectors (the length of the device's bio request
@ -59,6 +65,7 @@ static void tweak_SG_buffer(cdrom_drive *d) {
"table entry size: %d bytes\n\t"
"maximum theoretical transfer: %d sectors\n",
table, reserved, table*(reserved/CD_FRAMESIZE_RAW));
cdmessage(d,buffer);
cur=reserved; /* only use one entry for now */
@ -90,13 +97,23 @@ static void tweak_SG_buffer(cdrom_drive *d) {
if(cur==0) exit(1);
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
d->nsectors = 26; /* FreeBSD only supports 64K I/O transfer size */
d->bigbuff = d->nsectors * CD_FRAMESIZE_RAW;
sprintf(buffer,"\tSetting default read size to %d sectors (%d bytes).\n\n",
d->nsectors,d->nsectors*CD_FRAMESIZE_RAW);
#endif
cdmessage(d,buffer);
}
#if defined(__linux__)
static void clear_garbage(cdrom_drive *d){
fd_set fdset;
struct timeval tv;
struct sg_header *sg_hd=d->private->sg_hd;
struct sg_header *sg_hd=d->private_data->sg_hd;
int flag=0;
/* clear out any possibly preexisting garbage */
@ -123,6 +140,7 @@ static void clear_garbage(cdrom_drive *d){
flag=1;
}
}
#endif
static int check_sbp_error(const unsigned char status,
const unsigned char *sbp) {
@ -142,7 +160,11 @@ static int check_sbp_error(const unsigned char status,
case 1:
break;
case 2:
#ifdef ENOMEDIUM
errno = ENOMEDIUM;
#else
errno = EIO;
#endif
return(TR_NOTREADY);
case 3:
if ((ASC==0x0C) & (ASCQ==0x09)) {
@ -172,6 +194,7 @@ static int check_sbp_error(const unsigned char status,
return 0;
}
#ifdef __linux__
/* process a complete scsi command. */
static int sg2_handle_scsi_cmd(cdrom_drive *d,
unsigned char *cmd,
@ -185,7 +208,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
struct timespec tv2;
int tret1,tret2;
int status = 0;
struct sg_header *sg_hd=d->private->sg_hd;
struct sg_header *sg_hd=d->private_data->sg_hd;
long writebytes=SG_OFF+cmd_len+in_size;
/* generic scsi device services */
@ -195,7 +218,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
memset(sg_hd,0,sizeof(sg_hd));
memset(sense_buffer,0,SG_MAX_SENSE);
memcpy(d->private->sg_buffer,cmd,cmd_len+in_size);
memcpy(d->private_data->sg_buffer,cmd,cmd_len+in_size);
sg_hd->twelve_byte = cmd_len == 12;
sg_hd->result = 0;
sg_hd->reply_len = SG_OFF + out_size;
@ -209,7 +232,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
tell if the command failed. Scared yet? */
if(bytecheck && out_size>in_size){
memset(d->private->sg_buffer+cmd_len+in_size,bytefill,out_size-in_size);
memset(d->private_data->sg_buffer+cmd_len+in_size,bytefill,out_size-in_size);
/* the size does not remove cmd_len due to the way the kernel
driver copies buffers */
writebytes+=(out_size-in_size);
@ -243,7 +266,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
}
sigprocmask (SIG_BLOCK, &(d->sigset), NULL );
tret1=clock_gettime(d->private->clock,&tv1);
tret1=clock_gettime(d->private_data->clock,&tv1);
errno=0;
status = write(d->cdda_fd, sg_hd, writebytes );
@ -289,7 +312,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
}
}
tret2=clock_gettime(d->private->clock,&tv2);
tret2=clock_gettime(d->private_data->clock,&tv2);
errno=0;
status = read(d->cdda_fd, sg_hd, SG_OFF + out_size);
sigprocmask ( SIG_UNBLOCK, &(d->sigset), NULL );
@ -313,7 +336,7 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
if(bytecheck && in_size+cmd_len<out_size){
long i,flag=0;
for(i=in_size;i<out_size;i++)
if(d->private->sg_buffer[i]!=bytefill){
if(d->private_data->sg_buffer[i]!=bytefill){
flag=1;
break;
}
@ -326,9 +349,9 @@ static int sg2_handle_scsi_cmd(cdrom_drive *d,
errno=0;
if(tret1<0 || tret2<0){
d->private->last_milliseconds=-1;
d->private_data->last_milliseconds=-1;
}else{
d->private->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_nsec-tv1.tv_nsec)/1000000;
d->private_data->last_milliseconds = (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_nsec-tv1.tv_nsec)/1000000;
}
return(0);
}
@ -347,7 +370,7 @@ static int sgio_handle_scsi_cmd(cdrom_drive *d,
memset(&hdr,0,sizeof(hdr));
memset(sense,0,sizeof(sense));
memcpy(d->private->sg_buffer,cmd+cmd_len,in_size);
memcpy(d->private_data->sg_buffer,cmd+cmd_len,in_size);
hdr.cmdp = cmd;
hdr.cmd_len = cmd_len;
@ -355,7 +378,7 @@ static int sgio_handle_scsi_cmd(cdrom_drive *d,
hdr.mx_sb_len = SG_MAX_SENSE;
hdr.timeout = 50000;
hdr.interface_id = 'S';
hdr.dxferp = d->private->sg_buffer;
hdr.dxferp = d->private_data->sg_buffer;
hdr.flags = SG_FLAG_DIRECT_IO; /* direct IO if we can get it */
/* scary buffer fill hack */
@ -400,7 +423,7 @@ static int sgio_handle_scsi_cmd(cdrom_drive *d,
if(bytecheck && in_size<out_size){
long i,flag=0;
for(i=in_size;i<out_size;i++)
if(d->private->sg_buffer[i]!=bytefill){
if(d->private_data->sg_buffer[i]!=bytefill){
flag=1;
break;
}
@ -412,7 +435,7 @@ static int sgio_handle_scsi_cmd(cdrom_drive *d,
}
/* Can't rely on .duration because we can't be certain kernel has HZ set to something useful */
/* d->private->last_milliseconds = hdr.duration; */
/* d->private_data->last_milliseconds = hdr.duration; */
errno = 0;
return 0;
@ -432,6 +455,91 @@ static int handle_scsi_cmd(cdrom_drive *d,
return sg2_handle_scsi_cmd(d,cmd,cmd_len,in_size,out_size,bytefill,bytecheck,sense);
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int handle_scsi_cmd(cdrom_drive *d,
unsigned char *cmd,
unsigned int cmd_len,
unsigned int write_len,
unsigned int read_len,
unsigned char bytefill,
int bytecheck,
unsigned char *sense){
int result;
bzero(&d->private_data->ccb->csio, sizeof(d->private_data->ccb->csio));
memcpy(d->private_data->ccb->csio.cdb_io.cdb_bytes, cmd, cmd_len);
memcpy(d->private_data->sg_buffer, cmd + cmd_len, write_len);
if (bytecheck && (read_len > write_len))
memset(d->private_data->sg_buffer+write_len, bytefill, read_len - write_len);
cam_fill_csio(&d->private_data->ccb->csio,
/* retries */ 0,
/* cbfcnp */ NULL,
/* flags */ CAM_DEV_QFRZDIS | (write_len ? CAM_DIR_OUT : CAM_DIR_IN),
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* data_ptr */ d->private_data->sg_buffer,
/* dxfer_len */ write_len ? write_len : read_len,
/* sense_len */ SSD_FULL_SIZE,
/* cdb_len */ cmd_len,
/* timeout */ 60000); /* XXX */
result = cam_send_ccb(d->private_data->dev, d->private_data->ccb);
if ((result < 0) ||
(d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) == 0 /* hack? */)
return TR_EREAD;
if ((d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP &&
(d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR) {
fprintf (stderr, "\t\terror returned from SCSI command:\n"
"\t\tccb->ccb_h.status == %d\n", d->private_data->ccb->ccb_h.status);
errno = EIO;
return TR_UNKNOWN;
}
if (d->private_data->ccb->csio.dxfer_len != (write_len ? write_len : read_len)) {
errno = EIO;
return TR_EREAD;
}
int errorCode, senseKey, addSenseCode, addSenseCodeQual;
scsi_extract_sense( &(d->private_data->ccb->csio.sense_data), &errorCode, &senseKey, &addSenseCode,
&addSenseCodeQual );
if (errorCode) {
switch (senseKey) {
case SSD_KEY_NO_SENSE:
errno = EIO;
return TR_UNKNOWN;
case SSD_KEY_RECOVERED_ERROR:
break;
case SSD_KEY_NOT_READY:
errno = EBUSY;
return TR_BUSY;
case SSD_KEY_MEDIUM_ERROR:
errno = EIO;
if (addSenseCode == 0x0c &&
addSenseCodeQual == 0x09)
return TR_STREAMING;
else
return TR_MEDIUM;
case SSD_KEY_HARDWARE_ERROR:
errno = EIO;
return TR_FAULT;
case SSD_KEY_ILLEGAL_REQUEST:
errno = EINVAL;
return TR_ILLEGAL;
default:
errno = EIO;
return TR_UNKNOWN;
}
}
return 0;
}
#endif
static int test_unit_ready(cdrom_drive *d){
unsigned char sense[SG_MAX_SENSE];
@ -445,14 +553,15 @@ static int test_unit_ready(cdrom_drive *d){
handle_scsi_cmd(d, cmd, 6, 0, 56, 0,0, sense);
key = d->private->sg_buffer[2] & 0xf;
ASC = d->private->sg_buffer[12];
ASCQ = d->private->sg_buffer[13];
key = d->private_data->sg_buffer[2] & 0xf;
ASC = d->private_data->sg_buffer[12];
ASCQ = d->private_data->sg_buffer[13];
if(key == 2 && ASC == 4 && ASCQ == 1) return 0;
return 1;
}
#if defined(__linux__)
static void reset_scsi(cdrom_drive *d){
int arg,tries=0;
d->enable_cdda(d,0);
@ -471,6 +580,29 @@ static void reset_scsi(cdrom_drive *d){
d->enable_cdda(d,1);
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static void reset_scsi(cdrom_drive *d) {
d->enable_cdda(d,0);
d->private_data->ccb->ccb_h.func_code = XPT_RESET_DEV;
d->private_data->ccb->ccb_h.timeout = 5000;
cdmessage(d, "sending SCSI reset... ");
if (cam_send_ccb(d->private_data->dev, d->private_data->ccb)) {
cdmessage(d, "error sending XPT_RESET_DEV CCB");
} else {
if (((d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) ||
((d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))
cdmessage(d,"OK\n");
else
cdmessage(d,"FAILED\n");
}
d->enable_cdda(d,1);
}
#endif
static int mode_sense_atapi(cdrom_drive *d,int size,int page){
unsigned char sense[SG_MAX_SENSE];
@ -492,7 +624,7 @@ static int mode_sense_atapi(cdrom_drive *d,int size,int page){
if (handle_scsi_cmd (d, cmd, 10, 0, size+4,'\377',1,sense)) return(1);
{
unsigned char *b=d->private->sg_buffer;
unsigned char *b=d->private_data->sg_buffer;
if(b[0])return(1); /* Handles only up to 256 bytes */
if(b[6])return(1); /* Handles only up to 256 bytes */
@ -604,8 +736,8 @@ static int mode_select(cdrom_drive *d,int density,int secsize){
static unsigned int get_orig_sectorsize(cdrom_drive *d){
if(mode_sense(d,12,0x01))return(-1);
d->orgdens = d->private->sg_buffer[4];
return(d->orgsize = ((int)(d->private->sg_buffer[10])<<8)+d->private->sg_buffer[11]);
d->orgdens = d->private_data->sg_buffer[4];
return(d->orgsize = ((int)(d->private_data->sg_buffer[10])<<8)+d->private_data->sg_buffer[11]);
}
/* switch CDROM scsi drives to given sector size */
@ -664,8 +796,8 @@ static int scsi_read_toc (cdrom_drive *d){
return(-4);
}
first=d->private->sg_buffer[2];
last=d->private->sg_buffer[3];
first=d->private_data->sg_buffer[2];
last=d->private_data->sg_buffer[3];
tracks=last-first+1;
if (last > MAXTRK || first > MAXTRK || last<0 || first<0) {
@ -683,7 +815,7 @@ static int scsi_read_toc (cdrom_drive *d){
return(-5);
}
{
scsi_TOC *toc=(scsi_TOC *)(d->private->sg_buffer+4);
scsi_TOC *toc=(scsi_TOC *)(d->private_data->sg_buffer+4);
d->disc_toc[i-first].bFlags=toc->bFlags;
d->disc_toc[i-first].bTrack=i;
@ -704,7 +836,7 @@ static int scsi_read_toc (cdrom_drive *d){
return(-2);
}
{
scsi_TOC *toc=(scsi_TOC *)(d->private->sg_buffer+4);
scsi_TOC *toc=(scsi_TOC *)(d->private_data->sg_buffer+4);
d->disc_toc[i-first].bFlags=toc->bFlags;
d->disc_toc[i-first].bTrack=0xAA;
@ -738,7 +870,7 @@ static int scsi_read_toc2 (cdrom_drive *d){
}
/* copy to our structure and convert start sector */
tracks = d->private->sg_buffer[1];
tracks = d->private_data->sg_buffer[1];
if (tracks > MAXTRK) {
cderror(d,"003: CDROM reporting illegal number of tracks\n");
return(-3);
@ -754,33 +886,33 @@ static int scsi_read_toc2 (cdrom_drive *d){
return(-5);
}
d->disc_toc[i].bFlags = d->private->sg_buffer[10];
d->disc_toc[i].bFlags = d->private_data->sg_buffer[10];
d->disc_toc[i].bTrack = i + 1;
d->disc_toc[i].dwStartSector= d->adjust_ssize *
(((signed char)(d->private->sg_buffer[2])<<24) |
(d->private->sg_buffer[3]<<16)|
(d->private->sg_buffer[4]<<8)|
(d->private->sg_buffer[5]));
(((signed char)(d->private_data->sg_buffer[2])<<24) |
(d->private_data->sg_buffer[3]<<16)|
(d->private_data->sg_buffer[4]<<8)|
(d->private_data->sg_buffer[5]));
}
d->disc_toc[i].bFlags = 0;
d->disc_toc[i].bTrack = i + 1;
memcpy (&foo, d->private->sg_buffer+2, 4);
memcpy (&bar, d->private->sg_buffer+6, 4);
memcpy (&foo, d->private_data->sg_buffer+2, 4);
memcpy (&bar, d->private_data->sg_buffer+6, 4);
d->disc_toc[i].dwStartSector = d->adjust_ssize * (be32_to_cpu(foo) +
be32_to_cpu(bar));
d->disc_toc[i].dwStartSector= d->adjust_ssize *
((((signed char)(d->private->sg_buffer[2])<<24) |
(d->private->sg_buffer[3]<<16)|
(d->private->sg_buffer[4]<<8)|
(d->private->sg_buffer[5]))+
((((signed char)(d->private_data->sg_buffer[2])<<24) |
(d->private_data->sg_buffer[3]<<16)|
(d->private_data->sg_buffer[4]<<8)|
(d->private_data->sg_buffer[5]))+
((((signed char)(d->private->sg_buffer[6])<<24) |
(d->private->sg_buffer[7]<<16)|
(d->private->sg_buffer[8]<<8)|
(d->private->sg_buffer[9]))));
((((signed char)(d->private_data->sg_buffer[6])<<24) |
(d->private_data->sg_buffer[7]<<16)|
(d->private_data->sg_buffer[8]<<8)|
(d->private_data->sg_buffer[9]))));
d->cd_extra = FixupTOC(d,tracks+1);
@ -817,7 +949,7 @@ static int i_read_28 (cdrom_drive *d, void *p, long begin, long sectors, unsigne
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -836,7 +968,7 @@ static int i_read_A8 (cdrom_drive *d, void *p, long begin, long sectors, unsigne
cmd[9] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -854,7 +986,7 @@ static int i_read_D4_10 (cdrom_drive *d, void *p, long begin, long sectors, unsi
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -872,7 +1004,7 @@ static int i_read_D4_12 (cdrom_drive *d, void *p, long begin, long sectors, unsi
cmd[9] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -890,7 +1022,7 @@ static int i_read_D5 (cdrom_drive *d, void *p, long begin, long sectors, unsigne
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -908,7 +1040,7 @@ static int i_read_D8 (cdrom_drive *d, void *p, long begin, long sectors, unsigne
cmd[9] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -922,7 +1054,7 @@ static int i_read_mmc (cdrom_drive *d, void *p, long begin, long sectors, unsign
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -936,7 +1068,7 @@ static int i_read_mmcB (cdrom_drive *d, void *p, long begin, long sectors, unsig
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -950,7 +1082,7 @@ static int i_read_mmc2 (cdrom_drive *d, void *p, long begin, long sectors, unsig
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -964,7 +1096,7 @@ static int i_read_mmc2B (cdrom_drive *d, void *p, long begin, long sectors, unsi
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -978,7 +1110,7 @@ static int i_read_mmc3 (cdrom_drive *d, void *p, long begin, long sectors, unsig
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -992,7 +1124,7 @@ static int i_read_mmc3B (cdrom_drive *d, void *p, long begin, long sectors, unsi
cmd[8] = sectors;
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -1026,7 +1158,7 @@ static int i_read_msf (cdrom_drive *d, void *p, long begin, long sectors, unsign
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -1039,7 +1171,7 @@ static int i_read_msf2 (cdrom_drive *d, void *p, long begin, long sectors, unsig
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -1052,7 +1184,7 @@ static int i_read_msf3 (cdrom_drive *d, void *p, long begin, long sectors, unsig
if((ret=handle_scsi_cmd(d,cmd,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1,sense)))
return(ret);
if(p)memcpy(p,d->private->sg_buffer,sectors*CD_FRAMESIZE_RAW);
if(p)memcpy(p,d->private_data->sg_buffer,sectors*CD_FRAMESIZE_RAW);
return(0);
}
@ -1079,10 +1211,20 @@ static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors,
sprintf(b,"scsi_read error: sector=%ld length=%ld retry=%d\n",
begin,sectors,retry_count);
cdmessage(d,b);
#if defined(__linux__)
sprintf(b," Sense key: %x ASC: %x ASCQ: %x\n",
(int)(sense[2]&0xf),
(int)(sense[12]),
(int)(sense[13]));
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
int errorCode, senseKey, addSenseCode, addSenseCodeQual;
scsi_extract_sense( &(d->private_data->ccb->csio.sense_data), &errorCode, &senseKey, &addSenseCode,
&addSenseCodeQual );
sprintf(b," Sense key: %x ASC: %x ASCQ: %x\n",
senseKey,
addSenseCode,
addSenseCodeQual);
#endif
cdmessage(d,b);
sprintf(b," Transport error: %s\n",strerror_tr[err]);
cdmessage(d,b);
@ -1091,10 +1233,19 @@ static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors,
fprintf(stderr,"scsi_read error: sector=%ld length=%ld retry=%d\n",
begin,sectors,retry_count);
#if defined(__linux__)
fprintf(stderr," Sense key: %x ASC: %x ASCQ: %x\n",
(int)(sense[2]&0xf),
(int)(sense[12]),
(int)(sense[13]));
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
scsi_extract_sense( &(d->private_data->ccb->csio.sense_data), &errorCode, &senseKey, &addSenseCode,
&addSenseCodeQual );
fprintf(stderr," Sense key: %x ASC: %x ASCQ: %x\n",
senseKey,
addSenseCode,
addSenseCodeQual);
#endif
fprintf(stderr," Transport error: %s\n",strerror_tr[err]);
fprintf(stderr," System error: %s\n",strerror(errno));
}
@ -1120,10 +1271,11 @@ static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors,
}
sectors--;
continue;
#ifdef ENOMEDIUM
case ENOMEDIUM:
cderror(d,"404: No medium present\n");
return(-404);
#endif
default:
if(sectors==1){
if(errno==EIO)
@ -1275,7 +1427,7 @@ long scsi_read_msf3 (cdrom_drive *d, void *p, long begin,
static int count_2352_bytes(cdrom_drive *d){
long i;
for(i=2351;i>=0;i--)
if(d->private->sg_buffer[i]!=(unsigned char)'\177')
if(d->private_data->sg_buffer[i]!=(unsigned char)'\177')
return(((i+3)>>2)<<2);
return(0);
@ -1284,7 +1436,7 @@ static int count_2352_bytes(cdrom_drive *d){
static int verify_nonzero(cdrom_drive *d){
long i,flag=0;
for(i=0;i<2352;i++)
if(d->private->sg_buffer[i]!=0){
if(d->private_data->sg_buffer[i]!=0){
flag=1;
break;
}
@ -1587,6 +1739,7 @@ static void check_cache(cdrom_drive *d){
}
}
#if defined(__linux__)
static int check_atapi(cdrom_drive *d){
int atapiret=-1;
int fd = d->cdda_fd; /* check the device we'll actually be using to read */
@ -1618,6 +1771,47 @@ static int check_atapi(cdrom_drive *d){
}
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int
check_atapi(cdrom_drive *d)
{
bzero(&(&d->private_data->ccb->ccb_h)[1], sizeof(d->private_data->ccb->cpi) - sizeof(d->private_data->ccb->ccb_h));
d->private_data->ccb->ccb_h.func_code = XPT_PATH_INQ;
cdmessage(d, "\nChecking for ATAPICAM...\n");
if (cam_send_ccb(d->private_data->dev, d->private_data->ccb) < 0) {
cderror(d, "\terror sending XPT_PATH_INQ CCB: ");
cderror(d, cam_errbuf);
cderror(d, "\n");
return -1;
}
if ((d->private_data->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
cderror(d, "\tXPT_PATH_INQ CCB failed: ");
cderror(d, cam_errbuf);
cderror(d, "\n");
return -1;
}
/*
* if the bus device name is `ata', we're (obviously)
* running ATAPICAM.
*/
if (strncmp(d->private_data->ccb->cpi.dev_name, "ata", 3) == 0) {
cdmessage(d, "\tDrive is ATAPI (using ATAPICAM)\n");
d->is_atapi = 1;
} else {
cdmessage(d, "\tDrive is SCSI\n");
d->is_atapi = 0;
}
return d->is_atapi;
}
#endif
static int check_mmc(cdrom_drive *d){
unsigned char *b;
cdmessage(d,"\nChecking for MMC style command set...\n");
@ -1625,7 +1819,7 @@ static int check_mmc(cdrom_drive *d){
d->is_mmc=0;
if(mode_sense(d,22,0x2A)==0){
b=d->private->sg_buffer;
b=d->private_data->sg_buffer;
b+=b[3]+4;
if((b[0]&0x3F)==0x2A){
@ -1664,6 +1858,7 @@ static void check_exceptions(cdrom_drive *d,exception *list){
}
}
#ifdef __linux__
/* request vendor brand and model */
unsigned char *scsi_inquiry(cdrom_drive *d){
unsigned char sense[SG_MAX_SENSE];
@ -1673,8 +1868,9 @@ unsigned char *scsi_inquiry(cdrom_drive *d){
cderror(d,"008: Unable to identify CDROM model\n");
return(NULL);
}
return (d->private->sg_buffer);
return (d->private_data->sg_buffer);
}
#endif
int scsi_init_drive(cdrom_drive *d){
int ret;
@ -1742,8 +1938,12 @@ int scsi_init_drive(cdrom_drive *d){
check_cache(d);
d->error_retry=1;
d->private->sg_hd=realloc(d->private->sg_hd,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128);
d->private->sg_buffer=((unsigned char *)d->private->sg_hd)+SG_OFF;
#if defined(__linux__)
d->private_data->sg_hd=realloc(d->private_data->sg_hd,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128);
d->private_data->sg_buffer=((unsigned char *)d->private_data->sg_hd)+SG_OFF;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
d->private_data->sg_buffer==realloc(d->private_data->sg_buffer,d->nsectors * CD_FRAMESIZE_RAW + 128);
#endif
d->report_all=1;
return(0);
}

View File

@ -66,9 +66,9 @@ static long test_read(cdrom_drive *d, void *p, long begin, long sectors){
if(!fd)fd=fdopen(d->cdda_fd,"r");
if(begin<lastread)
d->private->last_milliseconds=20;
d->private_data->last_milliseconds=20;
else
d->private->last_milliseconds=sectors;
d->private_data->last_milliseconds=sectors;
#ifdef CDDA_TEST_UNDERRUN
sectors-=1;

View File

@ -1,4 +1,9 @@
#if defined (__linux__) || defined (__GLIBC__)
#include <endian.h>
#elif defined(__FreeBSD__)
#include <machine/endian.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>

46
main.c
View File

@ -51,7 +51,7 @@ static long parse_offset(cdrom_drive *d, char *offset, int begin){
if(offset==NULL)return(-1);
/* seperate track from time offset */
/* separate track from time offset */
temp=strchr(offset,']');
if(temp){
*temp='\0';
@ -213,6 +213,8 @@ VERSION"\n"
" -q --quiet : quiet operation\n"
" -e --stderr-progress : force output of progress information to\n"
" stderr (for wrapper scripts)\n"
" -E --force-progress-bar : force output of progress bar even if\n"
" stderr is not a terminal\n"
" -l --log-summary [<file>] : save result summary to file, default\n"
" filename cdparanoia.log\n"
" -L --log-debug [<file>] : save detailed device autosense and\n"
@ -221,14 +223,14 @@ VERSION"\n"
" -V --version : print version info and quit\n"
" -Q --query : autosense drive, query disc and quit\n"
" -B --batch : 'batch' mode (saves each track to a\n"
" seperate file.\n"
" separate file.\n"
" -s --search-for-drive : do an exhaustive search for drive\n"
" -h --help : print help\n\n"
" -p --output-raw : output raw 16 bit PCM in host byte \n"
" -p --output-raw : output raw 16-bit PCM in host byte \n"
" order\n"
" -r --output-raw-little-endian : output raw 16 bit little-endian PCM\n"
" -R --output-raw-big-endian : output raw 16 bit big-endian PCM\n"
" -r --output-raw-little-endian : output raw 16-bit little-endian PCM\n"
" -R --output-raw-big-endian : output raw 16-bit big-endian PCM\n"
" -w --output-wav : output as WAV file (default)\n"
" -f --output-aiff : output as AIFF file\n"
" -a --output-aifc : output as AIFF-C file\n\n"
@ -295,7 +297,7 @@ VERSION"\n"
" 1[ww:xx:yy.zz]-2[aa:bb:cc.dd] \n\n"
"Here, 1 and 2 are track numbers; the numbers in brackets provide a\n"
"finer grained offset within a particular track. [aa:bb:cc.dd] is in\n"
"finer-grained offset within a particular track. [aa:bb:cc.dd] is in\n"
"hours/minutes/seconds/sectors format. Zero fields need not be\n"
"specified: [::20], [:20], [20], [20.], etc, would be interpreted as\n"
"twenty seconds, [10:] would be ten minutes, [.30] would be thirty\n"
@ -303,7 +305,7 @@ VERSION"\n"
"When only a single offset is supplied, it is interpreted as a starting\n"
"offset and ripping will continue to the end of he track. If a single\n"
"offset is preceeded or followed by a hyphen, the implicit missing\n"
"offset is preceded or followed by a hyphen, the implicit missing\n"
"offset is taken to be the start or end of the disc, respectively. Thus:\n\n"
" 1:[20.35] Specifies ripping from track 1, second 20, sector 35 to \n"
@ -320,15 +322,18 @@ VERSION"\n"
" 2-4 Specifies ripping from the beginning of track two to the\n"
" end of track 4.\n\n"
"Don't forget to protect square brackets and preceeding hyphens from\n"
"Don't forget to protect square brackets and preceding hyphens from\n"
"the shell...\n\n"
"A few examples, protected from the shell:\n"
"Don't forget to protect square brackets from the shell...\n\n"
"A few examples, protected from the shell where appropriate:\n"
" A) query only with exhaustive search for a drive and full reporting\n"
" of autosense:\n"
" cdparanoia -vsQ\n\n"
" B) extract up to and including track 3, putting each track in a seperate\n"
" B) extract up to and including track 3, putting each track in a separate\n"
" file:\n"
" cdparanoia -B -- \"-3\"\n\n"
" cdparanoia -B -- -3\n\n"
" C) extract from track 1, time 0:30.12 to 1:10.00:\n"
" cdparanoia \"1[:30.12]-1[1:10]\"\n\n"
@ -338,6 +343,7 @@ VERSION"\n"
long callbegin;
long callend;
long callscript=0;
long force_progress_bar=0;
static char *callback_strings[16]={"wrote",
"finished",
@ -404,13 +410,13 @@ static void callback(long inpos, int function){
}
}
if(!quiet){
if(force_progress_bar || !quiet){
long test;
osector=inpos;
sector=inpos/CD_FRAMEWORDS;
if(printit==-1){
if(isatty(STDERR_FILENO)){
if(force_progress_bar || isatty(STDERR_FILENO)){
printit=1;
}else{
printit=0;
@ -604,10 +610,11 @@ static void callback(long inpos, int function){
memset(dispcache,' ',graph);
}
const char *optstring = "escCn:o:O:d:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
const char *optstring = "eEscCn:o:O:d:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
struct option options [] = {
{"stderr-progress",no_argument,NULL,'e'},
{"force-progress-bar",no_argument,NULL,'E'},
{"search-for-drive",no_argument,NULL,'s'},
{"force-cdrom-little-endian",no_argument,NULL,'c'},
{"force-cdrom-big-endian",no_argument,NULL,'C'},
@ -726,7 +733,7 @@ int main(int argc,char *argv[]){
break;
case 'g':
if(force_cooked_device){
report("-g option incompatable with -k\n");
report("-g option incompatible with -k\n");
exit(1);
}
force_cooked_device=NULL;
@ -735,7 +742,7 @@ int main(int argc,char *argv[]){
break;
case 'k':
if(force_generic_device || force_cdrom_device){
report("-k option incompatable with -d and -g\n");
report("-k option incompatible with -d and -g\n");
exit(1);
}
if(force_cooked_device)free(force_cooked_device);
@ -783,6 +790,9 @@ int main(int argc,char *argv[]){
callscript=1;
fprintf(stderr,"Sending all callbacks to stderr for wrapper script\n");
break;
case 'E':
force_progress_bar=1;
break;
case 'V':
fprintf(stderr,VERSION);
fprintf(stderr,"\n");
@ -1362,7 +1372,11 @@ int main(int argc,char *argv[]){
if(err)free(err);
if(mes)free(mes);
if(readbuf==NULL){
if(errno==EBADF || errno==ENOMEDIUM){
if(errno==EBADF
#ifdef ENOMEDIUM
|| errno==ENOMEDIUM
#endif
){
report("\nparanoia_read: CDROM drive unavailable, bailing.\n");
exit(1);
}

View File

@ -2439,6 +2439,7 @@ c_block *i_read_c_block(cdrom_paranoia *p,long beginword,long endword,
secread))<secread){
if(thisread<0){
#ifdef ENOMEDIUM
if(errno==ENOMEDIUM){
/* the one error we bail on immediately */
if(new)free_c_block(new);
@ -2446,6 +2447,7 @@ c_block *i_read_c_block(cdrom_paranoia *p,long beginword,long endword,
if(flags)free(flags);
return NULL;
}
#endif
thisread=0;
}
@ -2687,7 +2689,9 @@ int16_t *paranoia_read_limited(cdrom_paranoia *p, void(*callback)(long,int),
/* Was the medium removed or the device closed out from
under us? */
#ifdef ENOMEDIUM
if(errno==ENOMEDIUM) return NULL;
#endif
}
}

View File

@ -1,5 +1,9 @@
#include <stdlib.h>
#if defined (__linux__) || defined(__GLIBC__)
#include <endian.h>
#elif defined(__FreeBSD__)
#include <machine/endian.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>