#!/bin/sh # isopad [+] [-] isofile... # # The Linux IDE CD driver in 2.6 tries to read ahead, even past the end of the # CD or DVD. Even when the program issuing the original read request was only # trying to read legitimate parts of the disc (albeit near the end). # The result is spurious I/O errors and read failures. # It does not seem that this driver bug is going to be fixed soon. # # This program is intended to facilitate a workaround. It can pad (or unpad) # a .iso file so that, when it is burned, the resulting disc will allow # reads past the end of the content to succeed. # # "+" means pad the following .iso files. # "-" means remove all padding. # neither means test file and iso sizes. # # To see how much readahead is enabled on a drive: hdparm -a /dev/hdc # # Why do the padding in place, rather than on a copy of the file? # .iso files are usually quite large so copying takes a lot of time and space. # # Copyright 2005 D. Hugh Redelmeier # License: GPL # Version: Sat Jun 18 02:31:48 EDT 2005 # stop at the least sign of trouble set -u -e # op is "", "-", or "+": operation to be performed op="" for fn do case "$fn" in "-h"|"--help") echo "Usage: $0 [-|+|] isofile..." ;; "+"|"-") op="$fn" ;; *) isosize -x "$fn" isz=`isosize "$fn"` fsz=`stat --format='%s' "$fn"` # conventional block size for CDs bs=2048 # my guess at a sufficient amount of padding (in blocks) pb=64 if [ $fsz -lt $isz ] then echo "$fn is shorter ($fsz) than it should be ($isz)" >&2 exit 3 elif [ ` expr $fsz % $bs ` -ne 0 ] then echo "$fn file size ($fsz) is not a multiple of $bs" >&2 exit 4 elif [ ` expr $isz % $bs ` -ne 0 ] then echo "$fn isosize ($isz) is not a multiple of $bs" >&2 exit 5 else case "$op" in "") if [ $fsz -eq $isz ] then echo "$fn: isosize == file size == $fsz" else echo "$fn: isosize $isz; file size $fsz" fi ;; "+") echo "$fn: padding with $pb blocks of $bs zero bytes" dd if=/dev/zero bs=$bs count=$pb >>"$fn" ;; "-") if [ $fsz -eq $isz ] then echo "$fn: already $fsz bytes" else echo "$fn: truncating from $fsz to $isz bytes" dd if=/dev/null of="$fn" seek=$isz bs=1 fi ;; esac fi ;; esac done