|
Packit |
cb6d3d |
/*
|
|
Packit |
cb6d3d |
Copyright (C) 2004-2012, 2014-2015, 2017 Rocky Bernstein <rocky@gnu.org>
|
|
Packit |
cb6d3d |
Copyright (C) 2014 Robert Kausch <robert.kausch@freac.org>
|
|
Packit |
cb6d3d |
Copyright (C) 1998 Monty <xiphmont@mit.edu>
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
This program is free software: you can redistribute it and/or modify
|
|
Packit |
cb6d3d |
it under the terms of the GNU General Public License as published by
|
|
Packit |
cb6d3d |
the Free Software Foundation, either version 3 of the License, or
|
|
Packit |
cb6d3d |
(at your option) any later version.
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
This program is distributed in the hope that it will be useful,
|
|
Packit |
cb6d3d |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
cb6d3d |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
cb6d3d |
GNU General Public License for more details.
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
You should have received a copy of the GNU General Public License
|
|
Packit |
cb6d3d |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
See ChangeLog for recent changes.
|
|
Packit |
cb6d3d |
*/
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_CONFIG_H
|
|
Packit |
cb6d3d |
# include "config.h"
|
|
Packit |
cb6d3d |
# define __CDIO_CONFIG_H__ 1
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_STDIO_H
|
|
Packit |
cb6d3d |
# include <stdio.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_STDARG_H
|
|
Packit |
cb6d3d |
# include <stdarg.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_LIMITS_H
|
|
Packit |
cb6d3d |
#include <limits.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifndef PATH_MAX
|
|
Packit |
cb6d3d |
# ifdef MAXPATHLEN
|
|
Packit |
cb6d3d |
# define PATH_MAX MAXPATHLEN
|
|
Packit |
cb6d3d |
# else
|
|
Packit |
cb6d3d |
# define PATH_MAX 4096
|
|
Packit |
cb6d3d |
# endif
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_STDLIB_H
|
|
Packit |
cb6d3d |
# include <stdlib.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_UNISTD_H
|
|
Packit |
cb6d3d |
# include <unistd.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_STRING_H
|
|
Packit |
cb6d3d |
# include <string.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_FCNTL_H
|
|
Packit |
cb6d3d |
#include <fcntl.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#include "getopt.h"
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_ERRNO_H
|
|
Packit |
cb6d3d |
#include <errno.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifndef ENOMEDIUM
|
|
Packit |
cb6d3d |
#define ENOMEDIUM -1
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#include <math.h>
|
|
Packit |
cb6d3d |
#include <sys/time.h>
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifdef HAVE_SYS_STAT_H
|
|
Packit |
cb6d3d |
# include <sys/stat.h>
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#if !defined(HAVE_GETTIMEOFDAY)
|
|
Packit |
cb6d3d |
/* MinGW uses sys/time.h and sys/timeb.h to roll its own gettimeofday() */
|
|
Packit |
cb6d3d |
# if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_TIMEB_H)
|
|
Packit |
cb6d3d |
# include <sys/time.h>
|
|
Packit |
cb6d3d |
# include <sys/timeb.h>
|
|
Packit |
cb6d3d |
static void gettimeofday(struct timeval* tv, void* timezone);
|
|
Packit |
cb6d3d |
# endif
|
|
Packit |
cb6d3d |
#endif /* !defined(HAVE_GETTIMEOFDAY) */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#include <cdio/cdio.h>
|
|
Packit |
cb6d3d |
#include <cdio/cd_types.h>
|
|
Packit |
cb6d3d |
#include <cdio/paranoia/cdda.h>
|
|
Packit |
cb6d3d |
#include <cdio/paranoia/paranoia.h>
|
|
Packit |
cb6d3d |
#include <cdio/bytesex.h>
|
|
Packit |
cb6d3d |
#include <cdio/mmc.h>
|
|
Packit |
cb6d3d |
#include "utils.h"
|
|
Packit |
cb6d3d |
#include "report.h"
|
|
Packit |
cb6d3d |
#include "version.h"
|
|
Packit |
cb6d3d |
#include "header.h"
|
|
Packit |
cb6d3d |
#include "buffering_write.h"
|
|
Packit |
cb6d3d |
#include "cachetest.h"
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#ifndef O_BINARY
|
|
Packit |
cb6d3d |
#define O_BINARY 0
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* I wonder how many alignment issues this is gonna trip in the
|
|
Packit |
cb6d3d |
future... it shouldn't trip any... I guess we'll find out :) */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static int
|
|
Packit |
cb6d3d |
bigendianp(void)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
int test=1;
|
|
Packit |
cb6d3d |
char *hack=(char *)(&test);
|
|
Packit |
cb6d3d |
if(hack[0])return(0);
|
|
Packit |
cb6d3d |
return(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static long
|
|
Packit |
cb6d3d |
parse_offset(cdrom_drive_t *d, char *offset, int begin)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
track_t i_track= CDIO_INVALID_TRACK;
|
|
Packit |
cb6d3d |
long hours = -1;
|
|
Packit |
cb6d3d |
long minutes = -1;
|
|
Packit |
cb6d3d |
long seconds = -1;
|
|
Packit |
cb6d3d |
long sectors = -1;
|
|
Packit |
cb6d3d |
char *time = NULL;
|
|
Packit |
cb6d3d |
char *temp = NULL;
|
|
Packit |
cb6d3d |
long ret;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (!offset) return -1;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* separate track from time offset */
|
|
Packit |
cb6d3d |
temp=strchr(offset,']');
|
|
Packit |
cb6d3d |
if(temp){
|
|
Packit |
cb6d3d |
*temp='\0';
|
|
Packit |
cb6d3d |
temp=strchr(offset,'[');
|
|
Packit |
cb6d3d |
if(temp==NULL){
|
|
Packit |
cb6d3d |
report("Error parsing span argument");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
*temp='\0';
|
|
Packit |
cb6d3d |
time=temp+1;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* parse track */
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
int chars=strspn(offset,"0123456789");
|
|
Packit |
cb6d3d |
if(chars>0){
|
|
Packit |
cb6d3d |
offset[chars]='\0';
|
|
Packit |
cb6d3d |
i_track=atoi(offset);
|
|
Packit |
cb6d3d |
if ( i_track > d->tracks ) {
|
|
Packit |
cb6d3d |
/*take track i_first_track-1 as pre-gap of 1st track*/
|
|
Packit |
cb6d3d |
report("Track #%d does not exist.",i_track);
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
while(time){
|
|
Packit |
cb6d3d |
long val,chars;
|
|
Packit |
cb6d3d |
char *sec=strrchr(time,'.');
|
|
Packit |
cb6d3d |
if(!sec)sec=strrchr(time,':');
|
|
Packit |
cb6d3d |
if(!sec)sec=time-1;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
chars=strspn(sec+1,"0123456789");
|
|
Packit |
cb6d3d |
if(chars)
|
|
Packit |
cb6d3d |
val=atoi(sec+1);
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
val=0;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
switch(*sec){
|
|
Packit |
cb6d3d |
case '.':
|
|
Packit |
cb6d3d |
if(sectors!=-1){
|
|
Packit |
cb6d3d |
report("Error parsing span argument");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
sectors=val;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
default:
|
|
Packit |
cb6d3d |
if(seconds==-1)
|
|
Packit |
cb6d3d |
seconds=val;
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
if(minutes==-1)
|
|
Packit |
cb6d3d |
minutes=val;
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
if(hours==-1)
|
|
Packit |
cb6d3d |
hours=val;
|
|
Packit |
cb6d3d |
else{
|
|
Packit |
cb6d3d |
report("Error parsing span argument");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (sec<=time) break;
|
|
Packit |
cb6d3d |
*sec='\0';
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (i_track == CDIO_INVALID_TRACK) {
|
|
Packit |
cb6d3d |
if (seconds==-1 && sectors==-1) return -1;
|
|
Packit |
cb6d3d |
if (begin==-1) {
|
|
Packit |
cb6d3d |
ret=cdda_disc_firstsector(d);
|
|
Packit |
cb6d3d |
} else
|
|
Packit |
cb6d3d |
ret = begin;
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
if ( seconds==-1 && sectors==-1 ) {
|
|
Packit |
cb6d3d |
if (begin==-1){
|
|
Packit |
cb6d3d |
/* first half of a span */
|
|
Packit |
cb6d3d |
return(cdda_track_firstsector(d, i_track));
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
return(cdda_track_lastsector(d, i_track));
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
/* relative offset into a track */
|
|
Packit |
cb6d3d |
ret=cdda_track_firstsector(d, i_track);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* OK, we had some sort of offset into a track */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (sectors != -1) ret += sectors;
|
|
Packit |
cb6d3d |
if (seconds != -1) ret += seconds*CDIO_CD_FRAMES_PER_SEC;
|
|
Packit |
cb6d3d |
if (minutes != -1) ret += minutes*CDIO_CD_FRAMES_PER_MIN;
|
|
Packit |
cb6d3d |
if (hours != -1) ret += hours *60*CDIO_CD_FRAMES_PER_MIN;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* We don't want to outside of the track; if it's relative, that's OK... */
|
|
Packit |
cb6d3d |
if( i_track != CDIO_INVALID_TRACK ){
|
|
Packit |
cb6d3d |
if (cdda_sector_gettrack(d,ret) != i_track) {
|
|
Packit |
cb6d3d |
report("Time/sector offset goes beyond end of specified track.");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Don't pass up end of session */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if( ret>cdda_disc_lastsector(d) ) {
|
|
Packit |
cb6d3d |
report("Time/sector offset goes beyond end of disc.");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
return(ret);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static void
|
|
Packit |
cb6d3d |
display_toc(cdrom_drive_t *d)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
long audiolen=0;
|
|
Packit |
cb6d3d |
track_t i;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
report("\nTable of contents (audio tracks only):\n"
|
|
Packit |
cb6d3d |
"track length begin copy pre ch\n"
|
|
Packit |
cb6d3d |
"===========================================================");
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
for( i=1; i<=d->tracks; i++)
|
|
Packit |
cb6d3d |
if ( cdda_track_audiop(d,i) > 0 ) {
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
lsn_t sec=cdda_track_firstsector(d,i);
|
|
Packit |
cb6d3d |
lsn_t off=cdda_track_lastsector(d,i)-sec+1;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
report("%3d. %7ld [%02d:%02d.%02d] %7ld [%02d:%02d.%02d] %s %s %s",
|
|
Packit |
cb6d3d |
i,
|
|
Packit |
cb6d3d |
(long int) off,
|
|
Packit |
cb6d3d |
(int) (off/(CDIO_CD_FRAMES_PER_MIN)),
|
|
Packit |
cb6d3d |
(int) ((off/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
|
|
Packit |
cb6d3d |
(int) (off % CDIO_CD_FRAMES_PER_SEC),
|
|
Packit |
cb6d3d |
(long int) sec,
|
|
Packit |
cb6d3d |
(int) (sec/(CDIO_CD_FRAMES_PER_MIN)),
|
|
Packit |
cb6d3d |
(int) ((sec/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
|
|
Packit |
cb6d3d |
(int) (sec % CDIO_CD_FRAMES_PER_SEC),
|
|
Packit |
cb6d3d |
cdda_track_copyp(d,i)?" OK":" no",
|
|
Packit |
cb6d3d |
cdda_track_preemp(d,i)?" yes":" no",
|
|
Packit |
cb6d3d |
cdda_track_channels(d,i)==2?" 2":" 4");
|
|
Packit |
cb6d3d |
audiolen+=off;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("TOTAL %7ld [%02d:%02d.%02d] (audio only)",
|
|
Packit |
cb6d3d |
audiolen,
|
|
Packit |
cb6d3d |
(int) (audiolen/(CDIO_CD_FRAMES_PER_MIN)),
|
|
Packit |
cb6d3d |
(int) ((audiolen/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
|
|
Packit |
cb6d3d |
(int) (audiolen % CDIO_CD_FRAMES_PER_SEC));
|
|
Packit |
cb6d3d |
report(" ");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#include "usage.h"
|
|
Packit |
cb6d3d |
static void usage(FILE *f)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
fprintf( f, usage_help);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static long callbegin;
|
|
Packit |
cb6d3d |
static long callend;
|
|
Packit |
cb6d3d |
static long callscript=0;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static int skipped_flag=0;
|
|
Packit |
cb6d3d |
static int abort_on_skip=0;
|
|
Packit |
cb6d3d |
static FILE *logfile = NULL;
|
|
Packit |
cb6d3d |
static int logfile_open=0;
|
|
Packit |
cb6d3d |
static int reportfile_open=0;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#if TRACE_PARANOIA
|
|
Packit |
cb6d3d |
static void
|
|
Packit |
cb6d3d |
callback(long int inpos, paranoia_cb_mode_t function)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
#else
|
|
Packit |
cb6d3d |
static const char *callback_strings[16]={
|
|
Packit |
cb6d3d |
"read",
|
|
Packit |
cb6d3d |
"verify",
|
|
Packit |
cb6d3d |
"jitter",
|
|
Packit |
cb6d3d |
"correction",
|
|
Packit |
cb6d3d |
"scratch",
|
|
Packit |
cb6d3d |
"scratch repair",
|
|
Packit |
cb6d3d |
"skip",
|
|
Packit |
cb6d3d |
"drift",
|
|
Packit |
cb6d3d |
"backoff",
|
|
Packit |
cb6d3d |
"overlap",
|
|
Packit |
cb6d3d |
"dropped",
|
|
Packit |
cb6d3d |
"duped",
|
|
Packit |
cb6d3d |
"transport error",
|
|
Packit |
cb6d3d |
"cache error",
|
|
Packit |
cb6d3d |
"wrote",
|
|
Packit |
cb6d3d |
"finished",
|
|
Packit |
cb6d3d |
};
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static void
|
|
Packit |
cb6d3d |
callback(long int inpos, paranoia_cb_mode_t function)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
/*
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
(== PROGRESS == [--+!---x--------------> | 007218 01 ] == :-) . ==)
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
*/
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
int graph=30;
|
|
Packit |
cb6d3d |
char buffer[256];
|
|
Packit |
cb6d3d |
static long c_sector=0, v_sector=0;
|
|
Packit |
cb6d3d |
static char dispcache[]=" ";
|
|
Packit |
cb6d3d |
static int last=0;
|
|
Packit |
cb6d3d |
static long lasttime=0;
|
|
Packit |
cb6d3d |
long int sector, osector=0;
|
|
Packit |
cb6d3d |
struct timeval thistime;
|
|
Packit |
cb6d3d |
static char heartbeat=' ';
|
|
Packit |
cb6d3d |
int position=0,aheadposition=0;
|
|
Packit |
cb6d3d |
static int overlap=0;
|
|
Packit |
cb6d3d |
static int printit=-1;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static int slevel=0;
|
|
Packit |
cb6d3d |
static int slast=0;
|
|
Packit |
cb6d3d |
static int stimeout=0;
|
|
Packit |
cb6d3d |
static int cacheerr=0;
|
|
Packit |
cb6d3d |
const char *smilie="= :-)";
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (callscript)
|
|
Packit |
cb6d3d |
fprintf(stderr, "##: %d [%s] @ %ld\n",
|
|
Packit |
cb6d3d |
function, ((int) function >= 0 && (int) function < 16 ?
|
|
Packit |
cb6d3d |
callback_strings[function] : ""),
|
|
Packit |
cb6d3d |
inpos);
|
|
Packit |
cb6d3d |
else{
|
|
Packit |
cb6d3d |
if(function==PARANOIA_CB_CACHEERR){
|
|
Packit |
cb6d3d |
if(!cacheerr){
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"\rWARNING: The CDROM drive appears to be seeking impossibly quickly.\n"
|
|
Packit |
cb6d3d |
"This could be due to timer bugs, a drive that really is improbably fast,\n"
|
|
Packit |
cb6d3d |
"or, most likely, a bug in cdparanoia's cache modelling.\n\n"
|
|
Packit |
cb6d3d |
"Please consider using the -A option to perform an analysis run, then mail\n"
|
|
Packit |
cb6d3d |
"the cdparanoia.log file produced by the analysis to paranoia-dev@xiph.org\n"
|
|
Packit |
cb6d3d |
"to assist developers in correcting the problem.\n\n");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
cacheerr++;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(!quiet){
|
|
Packit |
cb6d3d |
long test;
|
|
Packit |
cb6d3d |
osector=inpos;
|
|
Packit |
cb6d3d |
sector=inpos/CD_FRAMEWORDS;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(printit==-1){
|
|
Packit |
cb6d3d |
if(isatty(STDERR_FILENO) || (logfile != NULL)){
|
|
Packit |
cb6d3d |
printit=1;
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
printit=0;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(printit==1){ /* else don't bother; it's probably being
|
|
Packit |
cb6d3d |
redirected */
|
|
Packit |
cb6d3d |
position=((float)(sector-callbegin)/
|
|
Packit |
cb6d3d |
(callend-callbegin))*graph;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
aheadposition=((float)(c_sector-callbegin)/
|
|
Packit |
cb6d3d |
(callend-callbegin))*graph;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(function == PARANOIA_CB_WROTE){
|
|
Packit |
cb6d3d |
v_sector=sector;
|
|
Packit |
cb6d3d |
return;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if (function == PARANOIA_CB_FINISHED) {
|
|
Packit |
cb6d3d |
last=8;
|
|
Packit |
cb6d3d |
heartbeat='*';
|
|
Packit |
cb6d3d |
slevel=0;
|
|
Packit |
cb6d3d |
v_sector=sector;
|
|
Packit |
cb6d3d |
} else
|
|
Packit |
cb6d3d |
if(position<graph && position>=0)
|
|
Packit |
cb6d3d |
switch(function){
|
|
Packit |
cb6d3d |
case PARANOIA_CB_VERIFY:
|
|
Packit |
cb6d3d |
if(stimeout>=30){
|
|
Packit |
cb6d3d |
if(overlap>CD_FRAMEWORDS)
|
|
Packit |
cb6d3d |
slevel=2;
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
slevel=1;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_READ:
|
|
Packit |
cb6d3d |
if(sector>c_sector)c_sector=sector;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
case PARANOIA_CB_FIXUP_EDGE:
|
|
Packit |
cb6d3d |
if(stimeout>=5){
|
|
Packit |
cb6d3d |
if(overlap>CD_FRAMEWORDS)
|
|
Packit |
cb6d3d |
slevel=2;
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
slevel=1;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(dispcache[position]==' ')
|
|
Packit |
cb6d3d |
dispcache[position]='-';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_FIXUP_ATOM:
|
|
Packit |
cb6d3d |
if(slevel<3 || stimeout>5)slevel=3;
|
|
Packit |
cb6d3d |
if(dispcache[position]==' ' ||
|
|
Packit |
cb6d3d |
dispcache[position]=='-')
|
|
Packit |
cb6d3d |
dispcache[position]='+';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_READERR:
|
|
Packit |
cb6d3d |
slevel=6;
|
|
Packit |
cb6d3d |
if(dispcache[position]!='V' && dispcache[position]!='C')
|
|
Packit |
cb6d3d |
dispcache[position]='e';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_CACHEERR:
|
|
Packit |
cb6d3d |
slevel=8;
|
|
Packit |
cb6d3d |
dispcache[position]='C';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_SKIP:
|
|
Packit |
cb6d3d |
slevel=8;
|
|
Packit |
cb6d3d |
if(dispcache[position]!='C')
|
|
Packit |
cb6d3d |
dispcache[position]='V';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_OVERLAP:
|
|
Packit |
cb6d3d |
overlap=osector;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_SCRATCH:
|
|
Packit |
cb6d3d |
slevel=7;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_DRIFT:
|
|
Packit |
cb6d3d |
if(slevel<4 || stimeout>5)slevel=4;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_FIXUP_DROPPED:
|
|
Packit |
cb6d3d |
case PARANOIA_CB_FIXUP_DUPED:
|
|
Packit |
cb6d3d |
slevel=5;
|
|
Packit |
cb6d3d |
if(dispcache[position]==' ' ||
|
|
Packit |
cb6d3d |
dispcache[position]=='-' ||
|
|
Packit |
cb6d3d |
dispcache[position]=='+')
|
|
Packit |
cb6d3d |
dispcache[position]='!';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_REPAIR:
|
|
Packit |
cb6d3d |
case PARANOIA_CB_BACKOFF:
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case PARANOIA_CB_WROTE:
|
|
Packit |
cb6d3d |
case PARANOIA_CB_FINISHED:
|
|
Packit |
cb6d3d |
/* Handled above */
|
|
Packit |
cb6d3d |
;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
switch(slevel){
|
|
Packit |
cb6d3d |
case 0: /* finished, or no jitter */
|
|
Packit |
cb6d3d |
if(skipped_flag)
|
|
Packit |
cb6d3d |
smilie=" 8-X";
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
smilie=" :^D";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1: /* normal. no atom, low jitter */
|
|
Packit |
cb6d3d |
smilie=" :-)";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 2: /* normal, overlap > 1 */
|
|
Packit |
cb6d3d |
smilie=" :-|";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 4: /* drift */
|
|
Packit |
cb6d3d |
smilie=" :-/";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 3: /* unreported loss of streaming */
|
|
Packit |
cb6d3d |
smilie=" :-P";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 5: /* dropped/duped bytes */
|
|
Packit |
cb6d3d |
smilie=" 8-|";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 6: /* scsi error */
|
|
Packit |
cb6d3d |
smilie=" :-0";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 7: /* scratch */
|
|
Packit |
cb6d3d |
smilie=" :-(";
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 8: /* skip */
|
|
Packit |
cb6d3d |
smilie=" ;-(";
|
|
Packit |
cb6d3d |
skipped_flag=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
gettimeofday(&thistime,NULL);
|
|
Packit |
cb6d3d |
test=thistime.tv_sec*10+thistime.tv_usec/100000;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (lasttime!=test || function == PARANOIA_CB_FINISHED
|
|
Packit |
cb6d3d |
|| slast!=slevel ) {
|
|
Packit |
cb6d3d |
if (lasttime!=test || function == PARANOIA_CB_FINISHED) {
|
|
Packit |
cb6d3d |
last++;
|
|
Packit |
cb6d3d |
lasttime=test;
|
|
Packit |
cb6d3d |
if(last>7)last=0;
|
|
Packit |
cb6d3d |
stimeout++;
|
|
Packit |
cb6d3d |
switch(last){
|
|
Packit |
cb6d3d |
case 0:
|
|
Packit |
cb6d3d |
heartbeat=' ';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1:case 7:
|
|
Packit |
cb6d3d |
heartbeat='.';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 2:case 6:
|
|
Packit |
cb6d3d |
heartbeat='o';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 3:case 5:
|
|
Packit |
cb6d3d |
heartbeat='0';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 4:
|
|
Packit |
cb6d3d |
heartbeat='O';
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(function == PARANOIA_CB_FINISHED)
|
|
Packit |
cb6d3d |
heartbeat='*';
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(slast!=slevel){
|
|
Packit |
cb6d3d |
stimeout=0;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
slast=slevel;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (abort_on_skip && skipped_flag
|
|
Packit |
cb6d3d |
&& function != PARANOIA_CB_FINISHED ) {
|
|
Packit |
cb6d3d |
sprintf(buffer,
|
|
Packit |
cb6d3d |
"\r (== PROGRESS == [%s| %06ld %02d ] ==%s %c ==) ",
|
|
Packit |
cb6d3d |
" ...aborting; please wait... ",
|
|
Packit |
cb6d3d |
v_sector,overlap/CD_FRAMEWORDS,smilie,heartbeat);
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
if(v_sector==0)
|
|
Packit |
cb6d3d |
sprintf(buffer,
|
|
Packit |
cb6d3d |
"\r (== PROGRESS == [%s| ...... %02d ] ==%s %c ==) ",
|
|
Packit |
cb6d3d |
dispcache,overlap/CD_FRAMEWORDS,smilie,heartbeat);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
sprintf(buffer,
|
|
Packit |
cb6d3d |
"\r (== PROGRESS == [%s| %06ld %02d ] ==%s %c ==) ",
|
|
Packit |
cb6d3d |
dispcache,v_sector,overlap/CD_FRAMEWORDS,smilie,heartbeat);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if ( aheadposition>=0 && aheadposition
|
|
Packit |
cb6d3d |
!(function == PARANOIA_CB_FINISHED) )
|
|
Packit |
cb6d3d |
buffer[aheadposition+19]='>';
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(isatty(STDERR_FILENO))
|
|
Packit |
cb6d3d |
fprintf(stderr, "%s", buffer);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (logfile != NULL && function == PARANOIA_CB_FINISHED) {
|
|
Packit |
cb6d3d |
fprintf(logfile, "%s", buffer+1);
|
|
Packit |
cb6d3d |
fprintf(logfile,"\n\n");
|
|
Packit |
cb6d3d |
fflush(logfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* clear the indicator for next batch */
|
|
Packit |
cb6d3d |
if(function == PARANOIA_CB_FINISHED)
|
|
Packit |
cb6d3d |
memset(dispcache,' ',graph);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
#endif /* !TRACE_PARANOIA */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static const char optstring[] = "aBcCd:eEfFg:k:hi:l:L:Am:n:o:O:pqQrRsS:Tt:VvwWx:XYZz::";
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static const struct option options [] = {
|
|
Packit |
cb6d3d |
{"abort-on-skip", no_argument, NULL, 'X'},
|
|
Packit |
cb6d3d |
{"analyze-drive", no_argument, NULL, 'A'},
|
|
Packit |
cb6d3d |
{"batch", no_argument, NULL, 'B'},
|
|
Packit |
cb6d3d |
{"disable-extra-paranoia", no_argument, NULL, 'Y'},
|
|
Packit |
cb6d3d |
{"disable-fragmentation", no_argument, NULL, 'F'},
|
|
Packit |
cb6d3d |
{"disable-paranoia", no_argument, NULL, 'Z'},
|
|
Packit |
cb6d3d |
{"force-cdrom-big-endian", no_argument, NULL, 'C'},
|
|
Packit |
cb6d3d |
{"force-cdrom-device", required_argument, NULL, 'd'},
|
|
Packit |
cb6d3d |
{"force-cdrom-little-endian", no_argument, NULL, 'c'},
|
|
Packit |
cb6d3d |
{"force-default-sectors", required_argument, NULL, 'n'},
|
|
Packit |
cb6d3d |
{"force-cooked-device", required_argument, NULL, 'k'},
|
|
Packit |
cb6d3d |
{"force-generic-device", required_argument, NULL, 'g'},
|
|
Packit |
cb6d3d |
{"force-read-speed", required_argument, NULL, 'S'},
|
|
Packit |
cb6d3d |
{"force-search-overlap", required_argument, NULL, 'o'},
|
|
Packit |
cb6d3d |
{"force-overread", no_argument, NULL, 'E'},
|
|
Packit |
cb6d3d |
{"help", no_argument, NULL, 'h'},
|
|
Packit |
cb6d3d |
{"log-summary", required_argument, NULL, 'l'},
|
|
Packit |
cb6d3d |
{"log-debug", required_argument, NULL, 'L'},
|
|
Packit |
cb6d3d |
{"mmc-timeout", required_argument, NULL, 'm'},
|
|
Packit |
cb6d3d |
{"never-skip", optional_argument, NULL, 'z'},
|
|
Packit |
cb6d3d |
{"output-aifc", no_argument, NULL, 'a'},
|
|
Packit |
cb6d3d |
{"output-aiff", no_argument, NULL, 'f'},
|
|
Packit |
cb6d3d |
{"output-raw", no_argument, NULL, 'p'},
|
|
Packit |
cb6d3d |
{"output-raw-big-endian", no_argument, NULL, 'R'},
|
|
Packit |
cb6d3d |
{"output-raw-little-endian", no_argument, NULL, 'r'},
|
|
Packit |
cb6d3d |
{"output-wav", no_argument, NULL, 'w'},
|
|
Packit |
cb6d3d |
{"query", no_argument, NULL, 'Q'},
|
|
Packit |
cb6d3d |
{"quiet", no_argument, NULL, 'q'},
|
|
Packit |
cb6d3d |
{"sample-offset", required_argument, NULL, 'O'},
|
|
Packit |
cb6d3d |
{"stderr-progress", no_argument, NULL, 'e'},
|
|
Packit |
cb6d3d |
{"test-mode", required_argument, NULL, 'x'},
|
|
Packit |
cb6d3d |
{"toc-bias", no_argument, NULL, 'T'},
|
|
Packit |
cb6d3d |
{"toc-offset", required_argument, NULL, 't'},
|
|
Packit |
cb6d3d |
{"verbose", no_argument, NULL, 'v'},
|
|
Packit |
cb6d3d |
{"version", no_argument, NULL, 'V'},
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
{NULL,0,NULL,0}
|
|
Packit |
cb6d3d |
};
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
static cdrom_drive_t *d = NULL;
|
|
Packit |
cb6d3d |
static cdrom_paranoia_t *p = NULL;
|
|
Packit |
cb6d3d |
static char *span = NULL;
|
|
Packit |
cb6d3d |
static char *force_cdrom_device = NULL;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#define free_and_null(p) \
|
|
Packit |
cb6d3d |
free(p); \
|
|
Packit |
cb6d3d |
p=NULL;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_TIMEB_H)
|
|
Packit |
cb6d3d |
static void
|
|
Packit |
cb6d3d |
gettimeofday(struct timeval* tv, void* timezone)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
struct timeb timebuffer;
|
|
Packit |
cb6d3d |
ftime( &timebuffer );
|
|
Packit |
cb6d3d |
tv->tv_sec=timebuffer.time;
|
|
Packit |
cb6d3d |
tv->tv_usec=1000*timebuffer.millitm;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* This is run automatically before leaving the program.
|
|
Packit |
cb6d3d |
Free allocated resources.
|
|
Packit |
cb6d3d |
*/
|
|
Packit |
cb6d3d |
static void
|
|
Packit |
cb6d3d |
cleanup (void)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
if (p) paranoia_free(p);
|
|
Packit |
cb6d3d |
if (d) cdda_close(d);
|
|
Packit |
cb6d3d |
free_and_null(force_cdrom_device);
|
|
Packit |
cb6d3d |
free_and_null(span);
|
|
Packit |
cb6d3d |
if(logfile_open) {
|
|
Packit |
cb6d3d |
fclose(logfile);
|
|
Packit |
cb6d3d |
logfile = NULL;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(reportfile_open) {
|
|
Packit |
cb6d3d |
fclose(reportfile);
|
|
Packit |
cb6d3d |
reportfile = NULL;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Returns true if we have an integer argument.
|
|
Packit |
cb6d3d |
If so, pi_arg is set.
|
|
Packit |
cb6d3d |
If no argument or integer argument found, we give an error
|
|
Packit |
cb6d3d |
message and return false.
|
|
Packit |
cb6d3d |
*/
|
|
Packit |
cb6d3d |
static bool
|
|
Packit |
cb6d3d |
get_int_arg(char c, long int *pi_arg)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
long int i_arg;
|
|
Packit |
cb6d3d |
char *p_end;
|
|
Packit |
cb6d3d |
if (!optarg) {
|
|
Packit |
cb6d3d |
/* This shouldn't happen, but we'll check anyway. */
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"An (integer) argument for option -%c was expected "
|
|
Packit |
cb6d3d |
" but not found. Option ignored\n", c);
|
|
Packit |
cb6d3d |
return false;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
errno = 0;
|
|
Packit |
cb6d3d |
i_arg = strtol(optarg, &p_end, 10);
|
|
Packit |
cb6d3d |
if ( (LONG_MIN == i_arg || LONG_MAX == i_arg) && (0 != errno) ) {
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"Value '%s' for option -%c out of range. Value %ld "
|
|
Packit |
cb6d3d |
"used instead.\n", optarg, c, i_arg);
|
|
Packit |
cb6d3d |
*pi_arg = i_arg;
|
|
Packit |
cb6d3d |
return false;
|
|
Packit |
cb6d3d |
} else if (*p_end) {
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"Can't convert '%s' for option -%c completely into an integer. "
|
|
Packit |
cb6d3d |
"Option ignored.\n", optarg, c);
|
|
Packit |
cb6d3d |
return false;
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
*pi_arg = i_arg;
|
|
Packit |
cb6d3d |
return true;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
int
|
|
Packit |
cb6d3d |
main(int argc,char *argv[])
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
int toc_bias = 0;
|
|
Packit |
cb6d3d |
int force_cdrom_endian = -1;
|
|
Packit |
cb6d3d |
int output_type = 1; /* 0=raw, 1=wav, 2=aifc */
|
|
Packit |
cb6d3d |
int output_endian = 0; /* -1=host, 0=little, 1=big */
|
|
Packit |
cb6d3d |
int query_only = 0;
|
|
Packit |
cb6d3d |
int batch = 0;
|
|
Packit |
cb6d3d |
int run_cache_test = 0;
|
|
Packit |
cb6d3d |
long int force_cdrom_overlap = -1;
|
|
Packit |
cb6d3d |
long int force_cdrom_sectors = -1;
|
|
Packit |
cb6d3d |
long int force_cdrom_speed = 0;
|
|
Packit |
cb6d3d |
long int force_overread = 0;
|
|
Packit |
cb6d3d |
long int sample_offset = 0;
|
|
Packit |
cb6d3d |
long int test_flags = 0;
|
|
Packit |
cb6d3d |
long int toc_offset = 0;
|
|
Packit |
cb6d3d |
long int max_retries = 20;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
char *logfile_name=NULL;
|
|
Packit |
cb6d3d |
char *reportfile_name=NULL;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* full paranoia, but allow skipping */
|
|
Packit |
cb6d3d |
int paranoia_mode=PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
int out;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
int c,long_option_index;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
atexit(cleanup);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
|
|
Packit |
cb6d3d |
switch(c){
|
|
Packit |
cb6d3d |
case 'a':
|
|
Packit |
cb6d3d |
output_type=2;
|
|
Packit |
cb6d3d |
output_endian=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'B':
|
|
Packit |
cb6d3d |
batch=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'c':
|
|
Packit |
cb6d3d |
force_cdrom_endian=0;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'C':
|
|
Packit |
cb6d3d |
force_cdrom_endian=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'e':
|
|
Packit |
cb6d3d |
callscript=1;
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"Sending all callback output to stderr for wrapper script\n");
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'f':
|
|
Packit |
cb6d3d |
output_type=3;
|
|
Packit |
cb6d3d |
output_endian=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'F':
|
|
Packit |
cb6d3d |
paranoia_mode&=~(PARANOIA_MODE_FRAGMENT);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'g':
|
|
Packit |
cb6d3d |
case 'k':
|
|
Packit |
cb6d3d |
case 'd':
|
|
Packit |
cb6d3d |
if (force_cdrom_device) {
|
|
Packit |
cb6d3d |
fprintf(stderr,
|
|
Packit |
cb6d3d |
"Multiple cdrom devices given. Previous device %s ignored\n",
|
|
Packit |
cb6d3d |
force_cdrom_device);
|
|
Packit |
cb6d3d |
free(force_cdrom_device);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
force_cdrom_device=strdup(optarg);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'h':
|
|
Packit |
cb6d3d |
usage(stdout);
|
|
Packit |
cb6d3d |
exit(0);
|
|
Packit |
cb6d3d |
case 'l':
|
|
Packit |
cb6d3d |
if(logfile_name)free(logfile_name);
|
|
Packit |
cb6d3d |
logfile_name=NULL;
|
|
Packit |
cb6d3d |
if(optarg)
|
|
Packit |
cb6d3d |
logfile_name=strdup(optarg);
|
|
Packit |
cb6d3d |
logfile_open=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'L':
|
|
Packit |
cb6d3d |
if(reportfile_name)free(reportfile_name);
|
|
Packit |
cb6d3d |
reportfile_name=NULL;
|
|
Packit |
cb6d3d |
if(optarg)
|
|
Packit |
cb6d3d |
reportfile_name=strdup(optarg);
|
|
Packit |
cb6d3d |
reportfile_open=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'm':
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
long int mmc_timeout_sec;
|
|
Packit |
cb6d3d |
if (get_int_arg(c, &mmc_timeout_sec)) {
|
|
Packit |
cb6d3d |
mmc_timeout_ms = 1000*mmc_timeout_sec;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'n':
|
|
Packit |
cb6d3d |
get_int_arg(c, &force_cdrom_sectors);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'o':
|
|
Packit |
cb6d3d |
get_int_arg(c, &force_cdrom_overlap);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'O':
|
|
Packit |
cb6d3d |
get_int_arg(c, &sample_offset);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'p':
|
|
Packit |
cb6d3d |
output_type=0;
|
|
Packit |
cb6d3d |
output_endian=-1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'r':
|
|
Packit |
cb6d3d |
output_type=0;
|
|
Packit |
cb6d3d |
output_endian=0;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'q':
|
|
Packit |
cb6d3d |
verbose=CDDA_MESSAGE_FORGETIT;
|
|
Packit |
cb6d3d |
quiet=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'Q':
|
|
Packit |
cb6d3d |
query_only=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'R':
|
|
Packit |
cb6d3d |
output_type=0;
|
|
Packit |
cb6d3d |
output_endian=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'S':
|
|
Packit |
cb6d3d |
get_int_arg(c, &force_cdrom_speed);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 't':
|
|
Packit |
cb6d3d |
get_int_arg(c, &toc_offset);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'T':
|
|
Packit |
cb6d3d |
toc_bias=-1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'v':
|
|
Packit |
cb6d3d |
verbose=CDDA_MESSAGE_PRINTIT;
|
|
Packit |
cb6d3d |
quiet=0;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'V':
|
|
Packit |
cb6d3d |
fprintf(stderr,PARANOIA_VERSION);
|
|
Packit |
cb6d3d |
fprintf(stderr,"\n");
|
|
Packit |
cb6d3d |
exit(0);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'w':
|
|
Packit |
cb6d3d |
output_type=1;
|
|
Packit |
cb6d3d |
output_endian=0;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'W':
|
|
Packit |
cb6d3d |
paranoia_mode&=~PARANOIA_MODE_REPAIR;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'x':
|
|
Packit |
cb6d3d |
get_int_arg(c, &test_flags);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'X':
|
|
Packit |
cb6d3d |
/*paranoia_mode&=~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);*/
|
|
Packit |
cb6d3d |
abort_on_skip=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'Y':
|
|
Packit |
cb6d3d |
paranoia_mode|=PARANOIA_MODE_OVERLAP; /* cdda2wav style overlap
|
|
Packit |
cb6d3d |
check only */
|
|
Packit |
cb6d3d |
paranoia_mode&=~PARANOIA_MODE_VERIFY;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'Z':
|
|
Packit |
cb6d3d |
paranoia_mode=PARANOIA_MODE_DISABLE;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'A':
|
|
Packit |
cb6d3d |
run_cache_test=1;
|
|
Packit |
cb6d3d |
query_only=1;
|
|
Packit |
cb6d3d |
reportfile_open=1;
|
|
Packit |
cb6d3d |
verbose=CDDA_MESSAGE_PRINTIT;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'z':
|
|
Packit |
cb6d3d |
if (optarg) {
|
|
Packit |
cb6d3d |
get_int_arg(c, &max_retries);
|
|
Packit |
cb6d3d |
paranoia_mode&=~PARANOIA_MODE_NEVERSKIP;
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
paranoia_mode|=PARANOIA_MODE_NEVERSKIP;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 'E':
|
|
Packit |
cb6d3d |
force_overread=1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
default:
|
|
Packit |
cb6d3d |
usage(stderr);
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(logfile_open){
|
|
Packit |
cb6d3d |
if(logfile_name==NULL)
|
|
Packit |
cb6d3d |
logfile_name=strdup("cdparanoia.log");
|
|
Packit |
cb6d3d |
if(!strcmp(logfile_name,"-")){
|
|
Packit |
cb6d3d |
logfile=stdout;
|
|
Packit |
cb6d3d |
logfile_open=0;
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
logfile=fopen(logfile_name,"w");
|
|
Packit |
cb6d3d |
if(logfile==NULL){
|
|
Packit |
cb6d3d |
report("Cannot open log summary file %s: %s",logfile_name,
|
|
Packit |
cb6d3d |
strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(reportfile_open){
|
|
Packit |
cb6d3d |
if(reportfile_name==NULL)
|
|
Packit |
cb6d3d |
reportfile_name=strdup("cdparanoia.log");
|
|
Packit |
cb6d3d |
if(!strcmp(reportfile_name,"-")){
|
|
Packit |
cb6d3d |
reportfile=stdout;
|
|
Packit |
cb6d3d |
reportfile_open=0;
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
if(logfile_name && !strcmp(reportfile_name,logfile_name)){
|
|
Packit |
cb6d3d |
reportfile=logfile;
|
|
Packit |
cb6d3d |
reportfile_open=0;
|
|
Packit |
cb6d3d |
}else{
|
|
Packit |
cb6d3d |
reportfile=fopen(reportfile_name,"w");
|
|
Packit |
cb6d3d |
if(reportfile==NULL){
|
|
Packit |
cb6d3d |
report("Cannot open debug log file %s: %s",reportfile_name,
|
|
Packit |
cb6d3d |
strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(logfile){
|
|
Packit |
cb6d3d |
/* log command line and version */
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
for (i = 0; i < argc; i++)
|
|
Packit |
cb6d3d |
fprintf(logfile,"%s ",argv[i]);
|
|
Packit |
cb6d3d |
fprintf(logfile,"\n");
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(reportfile!=logfile){
|
|
Packit |
cb6d3d |
fprintf(logfile,VERSION);
|
|
Packit |
cb6d3d |
fprintf(logfile,"\n");
|
|
Packit |
cb6d3d |
fprintf(logfile,"Using cdda library version: %s\n",cdda_version());
|
|
Packit |
cb6d3d |
fprintf(logfile,"Using paranoia library version: %s\n",paranoia_version());
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
fflush(logfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(reportfile && reportfile!=logfile){
|
|
Packit |
cb6d3d |
/* log command line */
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
for (i = 0; i < argc; i++)
|
|
Packit |
cb6d3d |
fprintf(reportfile,"%s ",argv[i]);
|
|
Packit |
cb6d3d |
fprintf(reportfile,"\n");
|
|
Packit |
cb6d3d |
fflush(reportfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(optind>=argc && !query_only){
|
|
Packit |
cb6d3d |
if(batch)
|
|
Packit |
cb6d3d |
span=NULL;
|
|
Packit |
cb6d3d |
else{
|
|
Packit |
cb6d3d |
/* D'oh. No span. Fetch me a brain, Igor. */
|
|
Packit |
cb6d3d |
usage(stderr);
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}else
|
|
Packit |
cb6d3d |
if (argv[optind]) span=strdup(argv[optind]);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
report(PARANOIA_VERSION);
|
|
Packit |
cb6d3d |
if(verbose){
|
|
Packit |
cb6d3d |
report("Using cdda library version: %s",cdda_version());
|
|
Packit |
cb6d3d |
report("Using paranoia library version: %s",paranoia_version());
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Query the cdrom/disc; we may need to override some settings */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(force_cdrom_device)
|
|
Packit |
cb6d3d |
d=cdda_identify(force_cdrom_device,verbose,NULL);
|
|
Packit |
cb6d3d |
else {
|
|
Packit |
cb6d3d |
driver_id_t driver_id;
|
|
Packit |
cb6d3d |
char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL,
|
|
Packit |
cb6d3d |
CDIO_FS_AUDIO,
|
|
Packit |
cb6d3d |
false,
|
|
Packit |
cb6d3d |
&driver_id);
|
|
Packit |
cb6d3d |
if (ppsz_cd_drives && *ppsz_cd_drives) {
|
|
Packit |
cb6d3d |
d=cdda_identify(*ppsz_cd_drives,verbose, NULL);
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
report("\nUnable find or access a CD-ROM drive with an audio CD"
|
|
Packit |
cb6d3d |
" in it.");
|
|
Packit |
cb6d3d |
report("\nYou might try specifying the drive, especially if it has"
|
|
Packit |
cb6d3d |
" mixed-mode (and non-audio) format tracks");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
cdio_free_device_list(ppsz_cd_drives);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(!d){
|
|
Packit |
cb6d3d |
if(!verbose)
|
|
Packit |
cb6d3d |
report("\nUnable to open cdrom drive; -v might give more information.");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(verbose)
|
|
Packit |
cb6d3d |
cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_PRINTIT);
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_FORGETIT);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* possibly force hand on endianness of drive, sector request size */
|
|
Packit |
cb6d3d |
if(force_cdrom_endian!=-1){
|
|
Packit |
cb6d3d |
d->bigendianp=force_cdrom_endian;
|
|
Packit |
cb6d3d |
switch(force_cdrom_endian){
|
|
Packit |
cb6d3d |
case 0:
|
|
Packit |
cb6d3d |
report("Forcing CDROM sense to little-endian; ignoring preset and autosense");
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1:
|
|
Packit |
cb6d3d |
report("Forcing CDROM sense to big-endian; ignoring preset and autosense");
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if (force_cdrom_sectors!=-1) {
|
|
Packit |
cb6d3d |
if(force_cdrom_sectors<0 || force_cdrom_sectors>100){
|
|
Packit |
cb6d3d |
report("Default sector read size must be 1<= n <= 100\n");
|
|
Packit |
cb6d3d |
cdda_close(d);
|
|
Packit |
cb6d3d |
d=NULL;
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("Forcing default to read %ld sectors; "
|
|
Packit |
cb6d3d |
"ignoring preset and autosense",force_cdrom_sectors);
|
|
Packit |
cb6d3d |
d->nsectors=force_cdrom_sectors;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if (force_cdrom_overlap!=-1) {
|
|
Packit |
cb6d3d |
if (force_cdrom_overlap<0 || force_cdrom_overlap>CDIO_CD_FRAMES_PER_SEC) {
|
|
Packit |
cb6d3d |
report("Search overlap sectors must be 0<= n <=75\n");
|
|
Packit |
cb6d3d |
cdda_close(d);
|
|
Packit |
cb6d3d |
d=NULL;
|
|
Packit |
cb6d3d |
if(logfile && logfile != stdout)
|
|
Packit |
cb6d3d |
fclose(logfile);
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("Forcing search overlap to %ld sectors; "
|
|
Packit |
cb6d3d |
"ignoring autosense",force_cdrom_overlap);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
switch( cdda_open(d) ) {
|
|
Packit |
cb6d3d |
case -2:case -3:case -4:case -5:
|
|
Packit |
cb6d3d |
report("\nUnable to open disc. Is there an audio CD in the drive?");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
case -6:
|
|
Packit |
cb6d3d |
report("\nCdparanoia could not find a way to read audio from this drive.");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
case 0:
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
default:
|
|
Packit |
cb6d3d |
report("\nUnable to open disc.");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
d->i_test_flags = test_flags;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (force_cdrom_speed == 0) force_cdrom_speed = -1;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (force_cdrom_speed != -1) {
|
|
Packit |
cb6d3d |
report("\nAttempting to set speed to %ldx... ", force_cdrom_speed);
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
if (verbose)
|
|
Packit |
cb6d3d |
report("\nAttempting to set cdrom to full speed... ");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (cdda_speed_set(d, force_cdrom_speed)) {
|
|
Packit |
cb6d3d |
if (verbose || force_cdrom_speed != -1)
|
|
Packit |
cb6d3d |
report("\tCDROM speed set FAILED. Continuing anyway...");
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
if (verbose)
|
|
Packit |
cb6d3d |
report("\tdrive returned OK.");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(run_cache_test){
|
|
Packit |
cb6d3d |
int warn=analyze_cache(d, stderr, reportfile, force_cdrom_speed);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(warn==0){
|
|
Packit |
cb6d3d |
reportC("\nDrive tests OK with Paranoia.\n\n");
|
|
Packit |
cb6d3d |
return 0;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(warn==1)
|
|
Packit |
cb6d3d |
reportC("\nWARNING! PARANOIA MAY NOT BE TRUSTWORTHY WITH THIS DRIVE!\n"
|
|
Packit |
cb6d3d |
"\nThe Paranoia library may not model this CDROM drive's cache"
|
|
Packit |
cb6d3d |
"\ncorrectly according to this analysis run. Analysis is not"
|
|
Packit |
cb6d3d |
"\nalways accurate (it can be fooled by machine load or random"
|
|
Packit |
cb6d3d |
"\nkernel latencies), but if a failed result happens more often"
|
|
Packit |
cb6d3d |
"\nthan one time in twenty on an unloaded machine, please mail"
|
|
Packit |
cb6d3d |
"\nthe %s file produced by this failed analysis to"
|
|
Packit |
cb6d3d |
"\nparanoia-dev@xiph.org to assist developers in extending"
|
|
Packit |
cb6d3d |
"\nParanoia to handle this CDROM properly.\n\n",reportfile_name);
|
|
Packit |
cb6d3d |
return 1;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Dump the TOC */
|
|
Packit |
cb6d3d |
if (query_only || verbose ) display_toc(d);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (query_only) exit(0);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* bias the disc. A hack. Of course. this is never the default. */
|
|
Packit |
cb6d3d |
/*
|
|
Packit |
cb6d3d |
Some CD-ROM/CD-R drives will add an offset to the position on
|
|
Packit |
cb6d3d |
reading audio data. This is usually around 500-700 audio samples
|
|
Packit |
cb6d3d |
(ca. 1/75 second) on reading. So when this program queries a
|
|
Packit |
cb6d3d |
specific sector, it might not receive exactly that sector, but
|
|
Packit |
cb6d3d |
shifted by some amount.
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
Note that if ripping includes the end of the CD, this will this
|
|
Packit |
cb6d3d |
cause this program to attempt to read partial sectors before or
|
|
Packit |
cb6d3d |
past the known user data area of the disc, probably causing read
|
|
Packit |
cb6d3d |
errors on most drives and possibly even hard lockups on some
|
|
Packit |
cb6d3d |
buggy hardware.
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
[Note to libcdio driver hackers: make sure all CD-drivers don't
|
|
Packit |
cb6d3d |
try to read outside of the stated disc boundaries.]
|
|
Packit |
cb6d3d |
*/
|
|
Packit |
cb6d3d |
if(sample_offset){
|
|
Packit |
cb6d3d |
toc_offset+=sample_offset/588;
|
|
Packit |
cb6d3d |
sample_offset%=588;
|
|
Packit |
cb6d3d |
if(sample_offset<0){
|
|
Packit |
cb6d3d |
sample_offset+=588;
|
|
Packit |
cb6d3d |
toc_offset--;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (toc_bias) {
|
|
Packit |
cb6d3d |
toc_offset = -cdda_track_firstsector(d,1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
for( i=0; i < d->tracks+1; i++ )
|
|
Packit |
cb6d3d |
d->disc_toc[i].dwStartSector+=toc_offset;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (d->nsectors==1) {
|
|
Packit |
cb6d3d |
report("WARNING: The autosensed/selected sectors per read value is\n"
|
|
Packit |
cb6d3d |
" one sector, making it very unlikely Paranoia can \n"
|
|
Packit |
cb6d3d |
" work.\n\n"
|
|
Packit |
cb6d3d |
" Attempting to continue...\n\n");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* parse the span, set up begin and end sectors */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
long i_first_lsn;
|
|
Packit |
cb6d3d |
long i_last_lsn;
|
|
Packit |
cb6d3d |
long batch_first;
|
|
Packit |
cb6d3d |
long batch_last;
|
|
Packit |
cb6d3d |
int batch_track;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (span) {
|
|
Packit |
cb6d3d |
/* look for the hyphen */
|
|
Packit |
cb6d3d |
char *span2=strchr(span,'-');
|
|
Packit |
cb6d3d |
if(strrchr(span,'-')!=span2){
|
|
Packit |
cb6d3d |
report("Error parsing span argument");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (span2!=NULL) {
|
|
Packit |
cb6d3d |
*span2='\0';
|
|
Packit |
cb6d3d |
span2++;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
i_first_lsn=parse_offset(d, span, -1);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(i_first_lsn==-1)
|
|
Packit |
cb6d3d |
i_last_lsn=parse_offset(d, span2, cdda_disc_firstsector(d));
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
i_last_lsn=parse_offset(d, span2, i_first_lsn);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (i_first_lsn == -1) {
|
|
Packit |
cb6d3d |
if (i_last_lsn == -1) {
|
|
Packit |
cb6d3d |
report("Error parsing span argument");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
i_first_lsn=cdda_disc_firstsector(d);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
if (i_last_lsn==-1) {
|
|
Packit |
cb6d3d |
if (span2) { /* There was a hyphen */
|
|
Packit |
cb6d3d |
i_last_lsn=cdda_disc_lastsector(d);
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
i_last_lsn=
|
|
Packit |
cb6d3d |
cdda_track_lastsector(d,cdda_sector_gettrack(d, i_first_lsn));
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
i_first_lsn = cdda_disc_firstsector(d);
|
|
Packit |
cb6d3d |
i_last_lsn = cdda_disc_lastsector(d);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
int track1 = cdda_sector_gettrack(d, i_first_lsn);
|
|
Packit |
cb6d3d |
int track2 = cdda_sector_gettrack(d, i_last_lsn);
|
|
Packit |
cb6d3d |
long off1 = i_first_lsn - cdda_track_firstsector(d, track1);
|
|
Packit |
cb6d3d |
long off2 = i_last_lsn - cdda_track_firstsector(d, track2);
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
for( i=track1; i<=track2; i++ )
|
|
Packit |
cb6d3d |
if(i != 0 && !cdda_track_audiop(d,i)){
|
|
Packit |
cb6d3d |
report("Selected span contains non audio track at track %02d. Aborting.\n\n", i);
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
report("Ripping from sector %7ld (track %2d [%d:%02d.%02d])\n"
|
|
Packit |
cb6d3d |
"\t to sector %7ld (track %2d [%d:%02d.%02d])\n",
|
|
Packit |
cb6d3d |
i_first_lsn,
|
|
Packit |
cb6d3d |
track1,
|
|
Packit |
cb6d3d |
(int) (off1/(CDIO_CD_FRAMES_PER_MIN)),
|
|
Packit |
cb6d3d |
(int) ((off1/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
|
|
Packit |
cb6d3d |
(int)(off1 % CDIO_CD_FRAMES_PER_SEC),
|
|
Packit |
cb6d3d |
i_last_lsn,
|
|
Packit |
cb6d3d |
track2,
|
|
Packit |
cb6d3d |
(int) (off2/(CDIO_CD_FRAMES_PER_MIN)),
|
|
Packit |
cb6d3d |
(int) ((off2/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
|
|
Packit |
cb6d3d |
(int)(off2 % CDIO_CD_FRAMES_PER_SEC));
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (toc_offset && !force_overread) {
|
|
Packit |
cb6d3d |
d->disc_toc[d->tracks].dwStartSector -= toc_offset;
|
|
Packit |
cb6d3d |
if (i_last_lsn > cdda_track_lastsector(d, d->tracks))
|
|
Packit |
cb6d3d |
i_last_lsn -= toc_offset;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
long cursor;
|
|
Packit |
cb6d3d |
int16_t offset_buffer[1176];
|
|
Packit |
cb6d3d |
int offset_buffer_used=0;
|
|
Packit |
cb6d3d |
int offset_skip=sample_offset*4;
|
|
Packit |
cb6d3d |
off_t sectorlen;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
#if defined(HAVE_GETUID) && (defined(HAVE_SETEUID) || defined(HAVE_SETEGID))
|
|
Packit |
cb6d3d |
int dummy __attribute__((unused));
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
p=paranoia_init(d);
|
|
Packit |
cb6d3d |
paranoia_modeset(p,paranoia_mode);
|
|
Packit |
cb6d3d |
if(force_cdrom_overlap!=-1)paranoia_overlapset(p,force_cdrom_overlap);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(verbose) {
|
|
Packit |
cb6d3d |
cdda_verbose_set(d,CDDA_MESSAGE_LOGIT,CDDA_MESSAGE_LOGIT);
|
|
Packit |
cb6d3d |
cdio_loglevel_default = CDIO_LOG_INFO;
|
|
Packit |
cb6d3d |
} else
|
|
Packit |
cb6d3d |
cdda_verbose_set(d,CDDA_MESSAGE_FORGETIT,CDDA_MESSAGE_FORGETIT);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
paranoia_seek(p,cursor=i_first_lsn,SEEK_SET);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* this is probably a good idea in general */
|
|
Packit |
cb6d3d |
#if defined(HAVE_GETUID) && defined(HAVE_SETEUID)
|
|
Packit |
cb6d3d |
dummy = seteuid(getuid());
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
#if defined(HAVE_GETGID) && defined(HAVE_SETEGID)
|
|
Packit |
cb6d3d |
dummy = setegid(getgid());
|
|
Packit |
cb6d3d |
#endif
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* we'll need to be able to read one sector past user data if we
|
|
Packit |
cb6d3d |
have a sample offset in order to pick up the last bytes. We
|
|
Packit |
cb6d3d |
need to set the disc length forward here so that the libs are
|
|
Packit |
cb6d3d |
willing to read past, assuming that works on the hardware, of
|
|
Packit |
cb6d3d |
course */
|
|
Packit |
cb6d3d |
if(sample_offset && force_overread)
|
|
Packit |
cb6d3d |
d->disc_toc[d->tracks].dwStartSector++;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
while(cursor<=i_last_lsn){
|
|
Packit |
cb6d3d |
char outfile_name[PATH_MAX];
|
|
Packit |
cb6d3d |
if ( batch ){
|
|
Packit |
cb6d3d |
batch_first = cursor;
|
|
Packit |
cb6d3d |
batch_track = cdda_sector_gettrack(d,cursor);
|
|
Packit |
cb6d3d |
batch_last = cdda_track_lastsector(d, batch_track);
|
|
Packit |
cb6d3d |
if (batch_last>i_last_lsn) batch_last=i_last_lsn;
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
batch_first = i_first_lsn;
|
|
Packit |
cb6d3d |
batch_last = i_last_lsn;
|
|
Packit |
cb6d3d |
batch_track = -1;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
callbegin=batch_first;
|
|
Packit |
cb6d3d |
callend=batch_last;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* argv[optind] is the span, argv[optind+1] (if exists) is outfile */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (optind+1
|
|
Packit |
cb6d3d |
if (!strcmp(argv[optind+1],"-") ){
|
|
Packit |
cb6d3d |
out = dup(fileno(stdout));
|
|
Packit |
cb6d3d |
if(out==-1){
|
|
Packit |
cb6d3d |
report("Cannot dupplicate stdout: %s",
|
|
Packit |
cb6d3d |
strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(batch)
|
|
Packit |
cb6d3d |
report("Are you sure you wanted 'batch' "
|
|
Packit |
cb6d3d |
"(-B) output with stdout?");
|
|
Packit |
cb6d3d |
report("outputting to stdout\n");
|
|
Packit |
cb6d3d |
if(logfile){
|
|
Packit |
cb6d3d |
fprintf(logfile,"outputting to stdout\n");
|
|
Packit |
cb6d3d |
fflush(logfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
outfile_name[0]='\0';
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
char dirname[PATH_MAX];
|
|
Packit |
cb6d3d |
char *basename=split_base_dir(argv[optind+1], dirname,
|
|
Packit |
cb6d3d |
PATH_MAX);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (NULL == basename) {
|
|
Packit |
cb6d3d |
report("Output filename too long");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(batch) {
|
|
Packit |
cb6d3d |
if (strlen(argv[optind+1]) - 10 > PATH_MAX) {
|
|
Packit |
cb6d3d |
report("Output filename too long");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
snprintf(outfile_name, PATH_MAX,
|
|
Packit |
cb6d3d |
" %strack%02d.%s", dirname,
|
|
Packit |
cb6d3d |
batch_track, basename);
|
|
Packit |
cb6d3d |
} else
|
|
Packit |
cb6d3d |
snprintf(outfile_name, PATH_MAX, "%s%s", dirname, basename);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(basename[0]=='\0'){
|
|
Packit |
cb6d3d |
switch (output_type) {
|
|
Packit |
cb6d3d |
case 0: /* raw */
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.raw", sizeof("cdda.raw"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.wav", sizeof("cdda.wav"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 2:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.aifc", sizeof("cdda.aifc"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 3:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.aiff", sizeof("cdda.aiff"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
out=open(outfile_name,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0666);
|
|
Packit |
cb6d3d |
if(out==-1){
|
|
Packit |
cb6d3d |
report("Cannot open specified output file %s: %s",
|
|
Packit |
cb6d3d |
outfile_name, strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("outputting to %s\n", outfile_name);
|
|
Packit |
cb6d3d |
if(logfile){
|
|
Packit |
cb6d3d |
fprintf(logfile,"outputting to %s\n",outfile_name);
|
|
Packit |
cb6d3d |
fflush(logfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
/* default */
|
|
Packit |
cb6d3d |
if (batch)
|
|
Packit |
cb6d3d |
sprintf(outfile_name,"track%02d.", batch_track);
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
outfile_name[0]='\0';
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
switch(output_type){
|
|
Packit |
cb6d3d |
case 0: /* raw */
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.raw", sizeof("cdda.raw"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.wav", sizeof("cdda.wav"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 2:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.aifc", sizeof("cdda.aifc"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 3:
|
|
Packit |
cb6d3d |
strncat(outfile_name, "cdda.aiff", sizeof("cdda.aiff"));
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
out = open(outfile_name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
|
|
Packit |
cb6d3d |
if(out==-1){
|
|
Packit |
cb6d3d |
report("Cannot open default output file %s: %s", outfile_name,
|
|
Packit |
cb6d3d |
strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("outputting to %s\n", outfile_name);
|
|
Packit |
cb6d3d |
if(logfile){
|
|
Packit |
cb6d3d |
fprintf(logfile,"outputting to %s\n",outfile_name);
|
|
Packit |
cb6d3d |
fflush(logfile);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
sectorlen = batch_last - batch_first + 1;
|
|
Packit |
cb6d3d |
if (cdda_sector_gettrack(d, cursor) == d->tracks &&
|
|
Packit |
cb6d3d |
toc_offset > 0 && !force_overread){
|
|
Packit |
cb6d3d |
sectorlen += toc_offset;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
switch(output_type) {
|
|
Packit |
cb6d3d |
case 0: /* raw */
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 1: /* wav */
|
|
Packit |
cb6d3d |
WriteWav(out, sectorlen * CD_FRAMESIZE_RAW);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 2: /* aifc */
|
|
Packit |
cb6d3d |
WriteAifc(out, sectorlen * CD_FRAMESIZE_RAW);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
case 3: /* aiff */
|
|
Packit |
cb6d3d |
WriteAiff(out, sectorlen * CD_FRAMESIZE_RAW);
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Off we go! */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(offset_buffer_used){
|
|
Packit |
cb6d3d |
/* partial sector from previous batch read */
|
|
Packit |
cb6d3d |
cursor++;
|
|
Packit |
cb6d3d |
if (buffering_write(out,
|
|
Packit |
cb6d3d |
((char *)offset_buffer)+offset_buffer_used,
|
|
Packit |
cb6d3d |
CDIO_CD_FRAMESIZE_RAW-offset_buffer_used)){
|
|
Packit |
cb6d3d |
report("Error writing output: %s", strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
skipped_flag=0;
|
|
Packit |
cb6d3d |
while(cursor<=batch_last){
|
|
Packit |
cb6d3d |
/* read a sector */
|
|
Packit |
cb6d3d |
int16_t *readbuf=paranoia_read_limited(p, callback, max_retries);
|
|
Packit |
cb6d3d |
char *err=cdda_errors(d);
|
|
Packit |
cb6d3d |
char *mes=cdda_messages(d);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(mes || err)
|
|
Packit |
cb6d3d |
fprintf(stderr,"\r "
|
|
Packit |
cb6d3d |
" \r%s%s\n",
|
|
Packit |
cb6d3d |
mes?mes:"",err?err:"");
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (err) free(err);
|
|
Packit |
cb6d3d |
if (mes) free(mes);
|
|
Packit |
cb6d3d |
if( readbuf==NULL) {
|
|
Packit |
cb6d3d |
if(errno==EBADF || errno==ENOMEDIUM){
|
|
Packit |
cb6d3d |
report("\nparanoia_read: CDROM drive unavailable, bailing.\n");
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
skipped_flag=1;
|
|
Packit |
cb6d3d |
report("\nparanoia_read: Unrecoverable error, bailing.\n");
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if(skipped_flag && abort_on_skip){
|
|
Packit |
cb6d3d |
cursor=batch_last+1;
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
skipped_flag=0;
|
|
Packit |
cb6d3d |
cursor++;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (output_endian!=bigendianp()) {
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
for (i=0; i
|
|
Packit |
cb6d3d |
readbuf[i]=UINT16_SWAP_LE_BE_C(readbuf[i]);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
callback(cursor*(CD_FRAMEWORDS)-1, PARANOIA_CB_WROTE);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (buffering_write(out,((char *)readbuf)+offset_skip,
|
|
Packit |
cb6d3d |
CDIO_CD_FRAMESIZE_RAW-offset_skip)){
|
|
Packit |
cb6d3d |
report("Error writing output: %s", strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
offset_skip=0;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if (output_endian != bigendianp()){
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
for (i=0; i
|
|
Packit |
cb6d3d |
readbuf[i] = UINT16_SWAP_LE_BE_C(readbuf[i]);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* One last bit of silliness to deal with sample offsets */
|
|
Packit |
cb6d3d |
if(sample_offset && cursor>batch_last){
|
|
Packit |
cb6d3d |
if (cdda_sector_gettrack(d, batch_last) < d->tracks || force_overread) {
|
|
Packit |
cb6d3d |
int i;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Need to flush the buffer when overreading into the leadout */
|
|
Packit |
cb6d3d |
if (cdda_sector_gettrack(d, batch_last) == d->tracks)
|
|
Packit |
cb6d3d |
paranoia_seek(p, cursor, SEEK_SET);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* read a sector and output the partial offset. Save the
|
|
Packit |
cb6d3d |
rest for the next batch iteration */
|
|
Packit |
cb6d3d |
readbuf=paranoia_read_limited(p,callback,max_retries);
|
|
Packit |
cb6d3d |
err=cdda_errors(d);mes=cdda_messages(d);
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(mes || err)
|
|
Packit |
cb6d3d |
fprintf(stderr,"\r "
|
|
Packit |
cb6d3d |
" \r%s%s\n",
|
|
Packit |
cb6d3d |
mes?mes:"",err?err:"");
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(err)free(err);if(mes)free(mes);
|
|
Packit |
cb6d3d |
if(readbuf==NULL){
|
|
Packit |
cb6d3d |
skipped_flag=1;
|
|
Packit |
cb6d3d |
report("\nparanoia_read: Unrecoverable error reading through "
|
|
Packit |
cb6d3d |
"sample_offset shift\n\tat end of track, bailing.\n");
|
|
Packit |
cb6d3d |
break;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
if (skipped_flag && abort_on_skip) break;
|
|
Packit |
cb6d3d |
skipped_flag=0;
|
|
Packit |
cb6d3d |
/* do not move the cursor */
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(output_endian!=bigendianp())
|
|
Packit |
cb6d3d |
for(i=0;i
|
|
Packit |
cb6d3d |
offset_buffer[i]=UINT16_SWAP_LE_BE_C(readbuf[i]);
|
|
Packit |
cb6d3d |
else
|
|
Packit |
cb6d3d |
memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
|
|
Packit |
cb6d3d |
offset_buffer_used=sample_offset*4;
|
|
Packit |
cb6d3d |
callback(cursor* (CD_FRAMEWORDS), PARANOIA_CB_WROTE);
|
|
Packit |
cb6d3d |
} else {
|
|
Packit |
cb6d3d |
memset(offset_buffer, 0, sizeof(offset_buffer));
|
|
Packit |
cb6d3d |
offset_buffer_used = sample_offset * 4;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
if(buffering_write(out,(char *)offset_buffer,
|
|
Packit |
cb6d3d |
offset_buffer_used)){
|
|
Packit |
cb6d3d |
report("Error writing output: %s", strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
/* Write sectors of silent audio to compensate for
|
|
Packit |
cb6d3d |
missing samples that would be in the leadout */
|
|
Packit |
cb6d3d |
if (cdda_sector_gettrack(d, batch_last) == d->tracks &&
|
|
Packit |
cb6d3d |
toc_offset > 0 && !force_overread)
|
|
Packit |
cb6d3d |
{
|
|
Packit |
cb6d3d |
char *silence;
|
|
Packit |
cb6d3d |
size_t missing_sector_bytes = CD_FRAMESIZE_RAW * toc_offset;
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
silence = calloc(toc_offset, CD_FRAMESIZE_RAW);
|
|
Packit |
cb6d3d |
if (!silence || buffering_write(out, silence, missing_sector_bytes)) {
|
|
Packit |
cb6d3d |
report("Error writing output: %s", strerror(errno));
|
|
Packit |
cb6d3d |
exit(1);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
free(silence);
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
callback(cursor* (CDIO_CD_FRAMESIZE_RAW/2)-1,
|
|
Packit |
cb6d3d |
PARANOIA_CB_FINISHED);
|
|
Packit |
cb6d3d |
buffering_close(out);
|
|
Packit |
cb6d3d |
if(skipped_flag){
|
|
Packit |
cb6d3d |
/* remove the file */
|
|
Packit |
cb6d3d |
report("\nRemoving aborted file: %s", outfile_name);
|
|
Packit |
cb6d3d |
unlink(outfile_name);
|
|
Packit |
cb6d3d |
/* make the cursor correct if we have another track */
|
|
Packit |
cb6d3d |
if(batch_track!=-1){
|
|
Packit |
cb6d3d |
batch_track++;
|
|
Packit |
cb6d3d |
cursor=cdda_track_firstsector(d,batch_track);
|
|
Packit |
cb6d3d |
paranoia_seek(p,cursor, SEEK_SET);
|
|
Packit |
cb6d3d |
offset_skip=sample_offset*4;
|
|
Packit |
cb6d3d |
offset_buffer_used=0;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
report("\n");
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
paranoia_free(p);
|
|
Packit |
cb6d3d |
p=NULL;
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
}
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
report("Done.\n\n");
|
|
Packit |
cb6d3d |
|
|
Packit |
cb6d3d |
return 0;
|
|
Packit |
cb6d3d |
}
|