chiark / gitweb /
dvdrip: Collect together bad-blocks lists from repeated runs.
[dvdrip] / dvdrip
1 #! /bin/bash -e
2
3 prog=${0##*/}
4 dev=${DVDRIP_DEVICE-/dev/dvd}
5 tmp=${DVDRIP_TMPDIR-${HOME?}/tmp/dvdrip}
6 archive=${DVDRIP_ARCHIVE-jem.distorted.org.uk:/mnt/dvd/archive}
7 : ${DVD_SECTOR_COPY=dvd-sector-copy}
8 : ${DVDRIP_UPLOAD=dvdrip-upload}
9 backup=nil eject=nil force=nil verbose=nil bogus=nil; unset dir sub n label
10 usage () {
11   cat <<EOF
12 usage: $prog [-befv] [-D DEV] [-a ARCH] [-d DIR]
13         [-l LABEL] [-n N] [-s SUB] [-t TMP] TITLE
14 EOF
15 }
16 while getopts "hD:a:bd:efl:n:s:t:v" opt; do
17   case $opt in
18     h) usage; exit 0 ;;
19     D) dev=$OPTARG ;;
20     a) archive=$OPTARG ;;
21     b) backup=t ;;
22     d) dir=$OPTARG ;;
23     e) eject=t ;;
24     f) force=t ;;
25     l) label=$OPTARG ;;
26     n) n=$OPTARG ;;
27     s) sub=$OPTARG ;;
28     t) tmp=$OPTARG ;;
29     v) verbose=t ;;
30     *) bogus=t ;;
31   esac
32 done
33 shift $(( $OPTIND - 1 ))
34 case $# in
35   1) title=$1 ;;
36   *) bogus=t ;;
37 esac
38 case $bogus in t) usage >&2; exit 2 ;; esac
39 case $verbose in t) set -x ;; esac
40 case $archive in
41   *:*) archhost=${archive%%:*} archpath=${archive#*:} ;;
42   *) unset archhost; archpath=$archive ;;
43 esac
44
45 notify () {
46   colour=$1 message=$2
47   echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)"
48 }
49 fail () { notify 1 "!!! $*"; exit 2; }
50 warn () { notify 5 "??? $*"; }
51 info () { notify 6 "--- $*"; }
52 run_setrc () {
53   notify 2 "+++ $*";
54   set +e; nice "$@"; rc=$?; set -e
55 }
56 run () { run_setrc "$@"; case $rc in 0) ;; *) fail "$1: exit $rc" ;; esac; }
57
58 archdo () {
59   op=$1; shift
60   case ${archhost+t} in
61     t)
62       qq=
63       for a in "$@"; do
64         qq="${qq:+$qq }'${a//\'/"'\\''"}'" #" # emacs is confused
65       done
66       "$op" ssh "$archhost" "$qq"
67       ;;
68     *)
69       "$op" "$@"
70       ;;
71   esac
72 }
73 archrun () { archdo run "$@"; }
74
75 case ${dir+t},${n+t} in
76   t,t | ,)
77     n=$(printf "%02d" "$n")
78     ;;
79   *)
80     echo >&2 "$prog: must specify both directory and disc number, or neither"
81     exit 2
82     ;;
83 esac
84
85 hack_label () {
86   tr "[:lower:]" "[:upper:]" |
87     tr -Cs "[:alnum:]_\n" "[-*]" |
88     sed 's/^-//; s/-$//'
89 }
90
91 case $backup in
92   t)
93     case ${label+t},${dir+t} in
94       t,*) ;;
95       ,) label=$(printf "%s" "$title" | hack_label) ;;
96       ,t) label=$(printf "%s_%s" "$dir" "$n" | hack_label) ;;
97     esac
98     len=$(printf "%s" "$label" | wc -c)
99     if [ $len -gt 32 ]; then echo >&2 "$prog: label too long"; exit 2; fi
100     ;;
101   nil)
102     case ${label+t} in
103       t) echo >&2 "$prog: label only meaningful to \`dvdbackup'"; exit 2 ;;
104     esac
105     ;;
106 esac
107
108 case ${dir+t} in
109   t) tag="${dir}_${n}_${title}" out="$dir/$n. $title" ;;
110   *) tag=$title out=$title ;;
111 esac
112 tag=${tag//\//_}
113
114 archdo run_setrc test -f "$archpath${sub+/$sub}/$out.iso"
115 case $rc,$force in
116   0,nil) fail "output file already exists" ;;
117   0,t) warn "output file already exists; will overwrite" ;;
118 esac
119
120 accumulate_badblocks () {
121   if [ -f "$tmp/$tag/badblocks.new" ]; then
122     if [ ! -f "$tmp/$tag/badblocks" ]; then
123       { echo "## bad-blocks region map"; echo; } >"$tmp/$tag/badblocks"
124     fi
125     sed -n "/^[^#]/p" "$tmp/$tag/badblocks.new" >>"$tmp/$tag/badblocks"
126     rm "$tmp/$tag/badblocks.new"
127   fi
128 }
129
130 mkdir -p "$tmp/$tag"
131 case $backup in
132   t)
133     if [ ! -d "$tmp/$tag/rip" ]; then
134       rm -rf "$tmp/$tag/rip.new"
135       run dvdbackup -Mp -i"$dev" -o"$tmp/$tag" -n"rip.new"
136       run mv "$tmp/$tag/rip.new" "$tmp/$tag/rip"
137     fi
138     if [ ! -f "$tmp/$tag/iso" ]; then
139       run genisoimage -quiet -dvd-video -udf -V "$label" \
140           -o "$tmp/$tag/iso.new" "$tmp/$tag/rip"
141       run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
142     fi
143     ;;
144   nil)
145     if [ ! -f "$tmp/$tag/iso" ]; then
146       accumulate_badblocks
147       run_setrc "$DVD_SECTOR_COPY" -c -b"$tmp/$tag/badblocks.new" \
148                 "$dev" "$tmp/$tag/iso.new"
149       accumulate_badblocks
150       case $rc in
151         0)
152           run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
153           ;;
154         1)
155           run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
156           fail "bad sectors found: check \`$tmp/$tag/iso', run again if ok"
157           ;;
158         *)
159           fail "$DVD_SECTOR_COPY: exit $rc"
160           ;;
161       esac
162     fi
163     ;;
164 esac
165 printf "%s\n" "${sub+$sub/}$out.iso" >"$tmp/$tag/dest.new"
166 mv "$tmp/$tag/dest.new" "$tmp/$tag/dest"
167 run "$DVDRIP_UPLOAD"
168 case $eject in t) run eject "$dev" ;; esac
169 printf "\a"