[plug] CD/DVD recovery
Brad Campbell
brad at wasp.net.au
Tue Aug 17 12:38:58 WST 2004
G'day all
For recovering badly scratched CD's I use cdparanoia. It might take 12 hours to read 1 3 minute song
but it gets the audio off. I never found anything that would work for CD's & DVD's to retrieve an
.iso image. A friend lent me some (ahem) cheap dvd's she picked up in a 3rd world country and I
noticed that most of them were either de-laminating, warped or so badly scratched they would not
even polish clean with toothpaste. Needless to say they were impossible to copy by regular means, so
I took this as a challenge. The script below is the result.
It reads a dvd/cd 10000*512 bytes at a time (dd standard blocks) and will retry a block until it's
blue in the face. If it reads a partial block it will take up reading from the end of the completed
portion next time and if it reads nothing it will wind back 10 blocks and have another go.
It took about 8 hours but it managed a complete read of the worst disk I have ever seen and the
image was then loopback mounted, ripped and de-css'd with vobcopy to play perfectly with xine. So I won!
I have 3 dvd readers. My laptop drive, my Internal dvd drive and my USB-2 DVD writer. One disk was
so bad that the internal and laptop drives would not even ack it existed. The dvd writer would
though and that is the one that took 8 hours to get a read.
You can resume the read on another drive by hand editing the POS value to the last POS it printed
before you gave it the ctrl-c.
I used it to move the read around the 3 different drives as some drives had better luck with certain
parts of the disk.
I post it here certainly not as an example of good bash code (or any code for that matter) but
simply hoping it might help someone one day.
It's a bit unorthodox in its usage of fdisk to determine the number of blocks on the disk, but it's
the only way I came up with from the shell. It's also dirty in the way it reads the output from dd
(I used to check dd's error code but I found it impossible to do if I was redirecting the output as
I ended up checking the errorcode of the redirection or I ended up grepping the result code. So I
just check to see if were at the end of the disk by total number of blocks or I check to see if we
spat out as many as we were asked to spit out.
Watch the wrap.
#!/bin/sh
BYTES=`fdisk -l /dev/scd0 | grep Disk | cut -f2 -d"," | cut -f2 -d" "`
BLOCKS=`dc -e "$BYTES 512 / p"`
echo $BLOCKS
COUNT=10000
POS=0
while [ "$POS" -le "$BLOCKS" ] ; do
let RETRY=1
let RCOUNT=0
while [ ! "$RETRY" -eq "0" ] ; do
COPIED=`dd if=/dev/scd0 of=/raid0/test.iso seek=$POS skip=$POS count=$COUNT 2>&1 | grep
"records out" | cut -f1 -d"+"`
echo -n Copied $COPIED blocks from $POS " "
let POS+=$COPIED
if [ "$COPIED" -ne "$COUNT" ] ; then
echo
echo Copied not equal to count!
if [ "$POS" -ne "$BLOCKS" ] ; then
echo And were not at end of disc
let RETRY=1
else echo Yahoo!!! End of disk!
exit 1
fi;
else let RETRY=0
fi;
if [ "$COPIED" -eq "0" ] ; then
let POS-=10
fi;
echo with Result $RETRY and $RCOUNT retries
let RCOUNT++
if [ "$RCOUNT" -ge "50" ] ; then
echo Ctrl-S here to clean disk
eject /dev/scd0
sleep 1
eject -t /dev/scd0
sleep 1
let RCOUNT=0
fi;
done;
done;
More information about the plug
mailing list