summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO21
-rw-r--r--PKGBUILD32
-rw-r--r--gcc.patch582
-rw-r--r--overread.patch243
4 files changed, 878 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..3db700c47295
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,21 @@
+pkgbase = cdparanoia-overread
+ pkgdesc = Compact Disc Digital Audio extraction tool patched for lead-out overread support
+ pkgver = 10.2
+ pkgrel = 1
+ url = http://www.xiph.org/paranoia/
+ arch = i686
+ arch = x86_64
+ license = GPL
+ depends = glibc
+ provides = cdparanoia
+ conflicts = cdparanoia
+ options = !makeflags
+ source = http://downloads.xiph.org/releases/cdparanoia/cdparanoia-III-10.2.src.tgz
+ source = gcc.patch
+ source = overread.patch
+ md5sums = b304bbe8ab63373924a744eac9ebc652
+ md5sums = 12da14958d2b84c6719fe69890436445
+ md5sums = 6016c653227b895939c3757fea002972
+
+pkgname = cdparanoia-overread
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..c83c9cde2298
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Samantha Baldwin <fuhsaz 'plus' aur 'at' cryptic 'dot' li>
+
+pkgname=cdparanoia-overread
+pkgver=10.2
+pkgrel=1
+pkgdesc="Compact Disc Digital Audio extraction tool patched for lead-out overread support"
+arch=('i686' 'x86_64')
+url="http://www.xiph.org/paranoia/"
+license=('GPL')
+depends=('glibc')
+options=('!makeflags')
+conflicts=('cdparanoia')
+provides=('cdparanoia')
+source=("http://downloads.xiph.org/releases/cdparanoia/cdparanoia-III-$pkgver.src.tgz"
+ 'gcc.patch'
+ 'overread.patch')
+md5sums=('b304bbe8ab63373924a744eac9ebc652'
+ '12da14958d2b84c6719fe69890436445'
+ '6016c653227b895939c3757fea002972')
+
+build() {
+ cd "${srcdir}/cdparanoia-III-${pkgver}"
+ patch -p0 -i ${srcdir}/gcc.patch
+ patch -p1 -i ${srcdir}/overread.patch
+ ./configure --prefix=/usr --mandir=/usr/share/man
+ make
+}
+
+package() {
+ cd "${srcdir}/cdparanoia-III-${pkgver}"
+ make prefix="${pkgdir}/usr" MANDIR="${pkgdir}/usr/share/man" install
+}
diff --git a/gcc.patch b/gcc.patch
new file mode 100644
index 000000000000..b157353e2865
--- /dev/null
+++ b/gcc.patch
@@ -0,0 +1,582 @@
+Index: interface/test_interface.c
+===================================================================
+--- interface/test_interface.c (Revision 15337)
++++ interface/test_interface.c (Revision 15340)
+@@ -66,9 +66,9 @@
+ 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;
+Index: interface/cdda_interface.h
+===================================================================
+--- interface/cdda_interface.h (Revision 15337)
++++ interface/cdda_interface.h (Revision 15340)
+@@ -84,7 +84,7 @@
+ int is_atapi;
+ int is_mmc;
+
+- cdda_private_data_t *private;
++ cdda_private_data_t *private_data;
+ void *reserved;
+ unsigned char inqbytes[4];
+
+Index: interface/interface.c
+===================================================================
+--- interface/interface.c (Revision 15337)
++++ interface/interface.c (Revision 15340)
+@@ -39,9 +39,9 @@
+ 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(d->private_data->sg_hd)free(d->private_data->sg_hd);
++ free(d->private_data);
+ }
+
+ free(d);
+@@ -127,7 +127,7 @@
+ }
+ }
+ }
+- if(ms)*ms=d->private->last_milliseconds;
++ if(ms)*ms=d->private_data->last_milliseconds;
+ return(sectors);
+ }
+
+Index: interface/scsi_interface.c
+===================================================================
+--- interface/scsi_interface.c (Revision 15337)
++++ interface/scsi_interface.c (Revision 15340)
+@@ -15,13 +15,13 @@
+ 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;
+ }
+@@ -96,7 +96,7 @@
+ 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 */
+@@ -185,7 +185,7 @@
+ 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 +195,7 @@
+
+ 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 +209,7 @@
+ 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 +243,7 @@
+ }
+
+ 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 +289,7 @@
+ }
+ }
+
+- 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 +313,7 @@
+ 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 +326,9 @@
+
+ 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 +347,7 @@
+
+ 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 +355,7 @@
+ 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 +400,7 @@
+ 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 +412,7 @@
+ }
+
+ /* 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;
+@@ -445,9 +445,9 @@
+
+ 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;
+@@ -492,7 +492,7 @@
+ 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 +604,8 @@
+ 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 +664,8 @@
+ 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 +683,7 @@
+ 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 +704,7 @@
+ 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 +738,7 @@
+ }
+
+ /* 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 +754,33 @@
+ 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 +817,7 @@
+ 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 +836,7 @@
+ 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 +854,7 @@
+ 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 +872,7 @@
+ 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 +890,7 @@
+ 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 +908,7 @@
+ 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 +922,7 @@
+ 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 +936,7 @@
+ 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 +950,7 @@
+ 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 +964,7 @@
+ 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 +978,7 @@
+ 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 +992,7 @@
+ 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 +1026,7 @@
+
+ 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 +1039,7 @@
+
+ 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 +1052,7 @@
+
+ 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);
+ }
+
+@@ -1275,7 +1275,7 @@
+ 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 +1284,7 @@
+ 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;
+ }
+@@ -1621,7 +1621,7 @@
+ 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){
+@@ -1669,7 +1669,7 @@
+ cderror(d,"008: Unable to identify CDROM model\n");
+ return(NULL);
+ }
+- return (d->private->sg_buffer);
++ return (d->private_data->sg_buffer);
+ }
+
+ int scsi_init_drive(cdrom_drive *d){
+@@ -1725,8 +1725,8 @@
+ 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;
++ 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;
+ d->report_all=1;
+ return(0);
+ }
+Index: interface/cooked_interface.c
+===================================================================
+--- interface/cooked_interface.c (Revision 15337)
++++ interface/cooked_interface.c (Revision 15340)
+@@ -13,13 +13,13 @@
+ 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;
+ }
+Index: interface/scan_devices.c
+===================================================================
+--- interface/scan_devices.c (Revision 15337)
++++ interface/scan_devices.c (Revision 15340)
+@@ -264,11 +264,11 @@
+ 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);
+@@ -674,15 +674,15 @@
+ 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 +696,8 @@
+ }
+
+ /* 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,9 +772,9 @@
+ 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);
+ }
+@@ -821,7 +821,7 @@
+ 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);
+
diff --git a/overread.patch b/overread.patch
new file mode 100644
index 000000000000..0dad2dc82e79
--- /dev/null
+++ b/overread.patch
@@ -0,0 +1,243 @@
+diff -aur cdparanoia-III-10.2.pristine/cdparanoia.1 cdparanoia-III-10.2.new/cdparanoia.1
+--- cdparanoia-III-10.2.pristine/cdparanoia.1 2013-09-13 03:17:17.992370058 -0400
++++ cdparanoia-III-10.2.new/cdparanoia.1 2013-09-13 03:17:45.698886625 -0400
+@@ -197,6 +197,11 @@
+ known user data area of the disc, probably causing read errors on most
+ drives and possibly even hard lockups on some buggy hardware.
+
++.TP
++.BI "\-x --force-overread
++Force overreading into the lead-out portion of the disc. This option is only applicable when using the
++.B -O
++option with a positive sample offset value. Many drives are not capable of reading into this portion of the disc and attempting to do so on those drives will produce read errors and possibly hard lockups.
+
+ .TP
+ .B \-Z --disable-paranoia
+diff -aur cdparanoia-III-10.2.pristine/main.c cdparanoia-III-10.2.new/main.c
+--- cdparanoia-III-10.2.pristine/main.c 2013-09-13 03:17:17.995703373 -0400
++++ cdparanoia-III-10.2.new/main.c 2013-09-13 03:17:49.542199138 -0400
+@@ -260,6 +260,7 @@
+ " correct\n"
+ " -O --sample-offset <n> : Add <n> samples to the offset when\n"
+ " reading data. May be negative.\n"
++" -x --force-overread : Enable overreading into the lead-out.\n"
+ " -z --never-skip[=n] : never accept any less than perfect\n"
+ " data reconstruction (don't allow 'V's)\n"
+ " but if [n] is given, skip after [n]\n"
+@@ -604,7 +605,7 @@
+ memset(dispcache,' ',graph);
+ }
+
+-const char *optstring = "escCn:o:O:d:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
++const char *optstring = "escCn:o:O:xd:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
+
+ struct option options [] = {
+ {"stderr-progress",no_argument,NULL,'e'},
+@@ -618,6 +619,7 @@
+ {"force-generic-device",required_argument,NULL,'g'},
+ {"force-read-speed",required_argument,NULL,'S'},
+ {"sample-offset",required_argument,NULL,'O'},
++ {"force-overread",no_argument,NULL,'x'},
+ {"toc-offset",required_argument,NULL,'t'},
+ {"toc-bias",no_argument,NULL,'T'},
+ {"output-raw",no_argument,NULL,'p'},
+@@ -679,6 +681,7 @@
+ char *force_generic_device=NULL;
+ char *force_cooked_device=NULL;
+ int force_cdrom_speed=0;
++ int force_overread=0;
+ int max_retries=20;
+ char *span=NULL;
+ int output_type=1; /* 0=raw, 1=wav, 2=aifc */
+@@ -686,6 +689,7 @@
+ int query_only=0;
+ int batch=0,i;
+ int run_cache_test=0;
++ int last_audio_track;
+
+ char *logfile_name=NULL;
+ char *reportfile_name=NULL;
+@@ -853,6 +857,9 @@
+ case 'O':
+ sample_offset=atoi(optarg);
+ break;
++ case 'x':
++ force_overread=1;
++ break;
+ default:
+ usage(stderr);
+ exit(1);
+@@ -1176,11 +1183,28 @@
+
+ }
+
++ last_audio_track = d->tracks;
++ if (toc_offset && !force_overread) {
++ int lt;
++
++ for (lt = d->tracks ; lt > 0 ; lt--)
++ if (cdda_track_audiop(d, lt))
++ break;
++
++ if (lt > 0)
++ last_audio_track = lt;
++
++ d->disc_toc[last_audio_track].dwStartSector -= toc_offset;
++ if (last_sector > cdda_track_lastsector(d, last_audio_track))
++ last_sector -= toc_offset;
++ }
++
+ {
+ long cursor;
+ int16_t offset_buffer[1176];
+ int offset_buffer_used=0;
+ int offset_skip=sample_offset*4;
++ off_t sectorlen;
+
+ p=paranoia_init(d);
+ paranoia_modeset(p,paranoia_mode);
+@@ -1202,7 +1226,7 @@
+ need to set the disc length forward here so that the libs are
+ willing to read past, assuming that works on the hardware, of
+ course */
+- if(sample_offset)
++ if(sample_offset && force_overread)
+ d->disc_toc[d->tracks].dwStartSector++;
+
+ while(cursor<=last_sector){
+@@ -1319,18 +1343,25 @@
+ fflush(logfile);
+ }
+ }
+-
++
++ sectorlen = batch_last - batch_first + 1;
++ if (cdda_sector_gettrack(d, cursor) == last_audio_track &&
++ toc_offset > 0 && !force_overread)
++ {
++ sectorlen += toc_offset;
++ }
++
+ switch(output_type){
+ case 0: /* raw */
+ break;
+ case 1: /* wav */
+- WriteWav(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
++ WriteWav(out, sectorlen * CD_FRAMESIZE_RAW);
+ break;
+ case 2: /* aifc */
+- WriteAifc(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
++ WriteAifc(out, sectorlen * CD_FRAMESIZE_RAW);
+ break;
+ case 3: /* aiff */
+- WriteAiff(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
++ WriteAiff(out, sectorlen * CD_FRAMESIZE_RAW);
+ break;
+ }
+
+@@ -1399,44 +1430,70 @@
+
+ /* One last bit of silliness to deal with sample offsets */
+ if(sample_offset && cursor>batch_last){
+- int i;
+- /* read a sector and output the partial offset. Save the
+- rest for the next batch iteration */
+- readbuf=paranoia_read_limited(p,callback,max_retries);
+- err=cdda_errors(d);mes=cdda_messages(d);
+-
+- if(mes || err)
+- fprintf(stderr,"\r "
+- " \r%s%s\n",
+- mes?mes:"",err?err:"");
+-
+- if(err)free(err);if(mes)free(mes);
+- if(readbuf==NULL){
+- skipped_flag=1;
+- report("\nparanoia_read: Unrecoverable error reading through "
+- "sample_offset shift\n\tat end of track, bailing.\n");
+- break;
+- }
+- if(skipped_flag && abort_on_skip)break;
+- skipped_flag=0;
+- /* do not move the cursor */
+-
+- if(output_endian!=bigendianp())
+- for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
+- offset_buffer[i]=swap16(readbuf[i]);
+- else
+- memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
+- offset_buffer_used=sample_offset*4;
+-
+- callback(cursor*(CD_FRAMEWORDS),-2);
++ if (cdda_sector_gettrack(d, batch_last) < last_audio_track || force_overread) {
++ int i;
+
+- if(buffering_write(out,(char *)offset_buffer,
++ /* Need to flush the buffer when overreading into the leadout */
++ if (cdda_sector_gettrack(d, batch_last) == last_audio_track)
++ paranoia_seek(p, cursor, SEEK_SET);
++
++ /* read a sector and output the partial offset. Save the
++ rest for the next batch iteration */
++ readbuf=paranoia_read_limited(p,callback,max_retries);
++ err=cdda_errors(d);mes=cdda_messages(d);
++
++ if(mes || err)
++ fprintf(stderr,"\r "
++ " \r%s%s\n",
++ mes?mes:"",err?err:"");
++
++ if(err)free(err);if(mes)free(mes);
++ if(readbuf==NULL){
++ skipped_flag=1;
++ report("\nparanoia_read: Unrecoverable error reading through "
++ "sample_offset shift\n\tat end of track, bailing.\n");
++ break;
++ }
++ if(skipped_flag && abort_on_skip)break;
++ skipped_flag=0;
++ /* do not move the cursor */
++
++ if(output_endian!=bigendianp())
++ for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
++ offset_buffer[i]=swap16(readbuf[i]);
++ else
++ memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
++ offset_buffer_used=sample_offset*4;
++ callback(cursor*(CD_FRAMEWORDS),-2);
++ } else {
++ memset(offset_buffer, 0, sizeof(offset_buffer));
++ offset_buffer_used = sample_offset * 4;
++ }
++
++ if(buffering_write(out,(char *)offset_buffer,
+ offset_buffer_used)){
+- report("Error writing output: %s",strerror(errno));
+- exit(1);
+- }
+- }
++ report("Error writing output: %s",strerror(errno));
++ exit(1);
++ }
++ }
+ }
++
++ /* Write sectors of silent audio to compensate for
++ missing samples that would be in the leadout */
++ if (cdda_sector_gettrack(d, batch_last) == last_audio_track &&
++ toc_offset > 0 && !force_overread)
++ {
++ char *silence;
++ size_t missing_sector_bytes = CD_FRAMESIZE_RAW * toc_offset;
++
++ silence = calloc(toc_offset, CD_FRAMESIZE_RAW);
++ if (!silence || buffering_write(out, silence, missing_sector_bytes)) {
++ report("Error writing output: %s", strerror(errno));
++ exit(1);
++ }
++ free(silence);
++ }
++
+ callback(cursor*(CD_FRAMESIZE_RAW/2)-1,-1);
+ buffering_close(out);
+ if(skipped_flag){