-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathisosuck
executable file
·228 lines (196 loc) · 6.42 KB
/
isosuck
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/bin/sh
version="1.1.0.20210912"
help() { cat <</help
Usage: isosuck [DVD Title] [DVD DEVICE]
DVD Title will default to the volume ID of the DVD
Output will be <DVD Title>.iso
DVD DEVICE will default to /dev/dvd
isosuck $version Copyright 2010+ by Adam Katz, GPLv2
Learn more at https://github.com/adamhotep/media-scripts
/help
exit
}
version() { cat <</version
isosuck $version
Copyright (C) 2010+ Adam Katz
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
/version
exit
}
license() { cat <</license
Copyright (C) 2010+ Adam Katz
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
/license
exit
}
# silently returns true only when we have all of the given command(s)
we_have() { command -v "$@" >/dev/null 2>&1; }
# print the arguments and exit the entire program
die() { echo "$*" >&2; exit 2; }
while getopts hLV-: OPT; do
case "$OPT" in
(h) help ;;
(L) license ;;
(V) version ;;
(-) case "$OPTARG" in
(help) help ;;
(license) license ;;
(version) version ;;
(*) die "Illegal option --$OPTARG ... Try --help" ;;
esac ;;
(\?) die "Try --help" ;;
esac
done
shift $((OPTIND-1))
if ! we_have isoinfo; then
echo "This program requires isoinfo; try installing genisoimage or cdrkit" >&2
exit 2
fi
# Get title from command line argument, strip trailing `.iso` (we add it later)
title="${1%.iso}"
for device in "$2" "/dev/dvd" "/dev/sr0" "/dev/sr1" "/dev/sr2" "/dev/sr3"; do
if [ -b "$device" ]; then
break
fi
done
if [ ! -b "$device" ]; then
echo "ERROR: Could not find an appropriate DVD device." >&2
exit 2
elif [ -n "$2" ] && [ "$2" != "$device" ]; then
echo "WARNING: '$2' is not a block device, using '$device' instead." >&2
sleep 1
fi
dvdinfo() { isoinfo -d -i "$device" 2>/dev/null; }
if we_have dc3dd; then
image() { dc3dd hash=md5 if="$device" of="$1"; }
else
if we_have md5sum; then # GNU
hash() { md5sum "$1" |awk '{print $1}'; }
elif we_have md5; then # BSD
hash() { md5 "$1" |awk '{print $NF}'; }
elif we_have cksum; then # old POSIX (use sum and size)
hash() { cksum "$1" |awk '{print $1,$2}'; }
else # wtf, no cksum?! use just size
hash() { /bin/ls -l "$1" |awk '{print $5}'; }
fi
image() {
local retval orig new
dd if="$device" of="$1"
retval=$?
if [ $retval != 0 ]; then
echo "WARNING: dd did not exit cleanly (code $retval)" >&2
echo " (performing hash check anyway, may be a waste of time)" >&2
fi
orig="$(hash "$device")"
new="$(hash "$1")"
if [ "$orig" != "$new" ]; then
echo "FAILURE: Hash mismatch on output '$1'" >&2
return 1
else
echo "Success: Hash matches original source."
fi
return $retval
}
fi
default_title=DVD_VIDEO
if [ -z "$title" ]; then
title="$(dvdinfo |sed '/^Volume id: /!d; s///')"
fi
if [ -z "$title" ]; then
title="DVD_VIDEO"
fi
if [ "$title" = "$default_title" ]; then
i=1
base="$default_title"
while [ -s "$title.iso" ]; do
title="$base-$i"
i=$((i+1))
done
fi
if [ -s "$title.iso" ]; then
echo "Output '$title.iso' already exists, aborting." >&2
exit 1
fi
# not posix but present nearly everwhere (GNU coreutils, BSD). Fallback:
if ! we_have readlink; then
# Usage: readlink [-f] LINK
# Print the target of given LINK, keep following given -f, limit=100 (~0.33s)
readlink() {
local canonicalize= file="$1" target= i=0
case "$1" in ( -f | --canonicalize ) canonicalize=1 file="$2" ;; esac
if [ -n "${file##/*}" ]; then file="$PWD/$file"; fi
while [ -L "$file" ] && [ $i -le 100 ]; do
target="$(ls -dl "$file")" || break
target="${target#* $file -> }"
if [ -n "${target##/*}" ]; then target="${file%/*}/$target"; fi
if [ -e "$target" ]; then file="$target"; else break; fi
if [ -z "$canonicalize" ]; then break; fi
i=$((i+1))
done
echo "$file"
}
fi
true_device="$(readlink -f "$device" 2>/dev/null || echo "$device")"
mounted="$(mount |awk -v dvd="$true_device" '$1 == dvd')"
mounted="${mounted#* on /}"
mounted="${mounted% type *}"
oldtitle="${mounted##*/}"
if [ -n "$mounted" ] && [ "$mounted" = "${mounted%*/$title}" ]; then
mounted="/$mounted"
echo "WARNING: You appear to have a different DVD ($oldtitle) mounted."
echo " This could result in the output being truncated."
echo " I'll UNMOUNT '$mounted' in five seconds. You've been warned."
sleep 5
umount "$mounted" || sudo umount -v "$mounted"
fi
location="$(dirname "$title.iso")"
free="$(df -k "$location" |awk 'NR==2 && $4 { print $4 }')"
size="$(dvdinfo |awk '
/^Logical block size is:/ { block = $NF }
/^Volume size is:/ { vol = $NF }
END {
size = sprintf("%.0f", block * vol / 1024)
min = 4 * 1024^2 # a minimum size in case isoinfo fails
printf "%.0f", (size > min ? size : min)
}
')"
awk -v title="$title" -v size="$size" -v device="$device" 'BEGIN {
printf "Will write `%s.iso` (%.2fG) from `%s`", title, size / 1024^2, device
}'
sleep 2
# warn if we'd have less than 1GB free after ripping
if [ $size -ge $((free-1024*1024)) ]; then
awk -v size="$size" -v free="$free" 'BEGIN {
printf "WARNING: Disk image is %.2fG but we only have %.2fG free space\n",
size / 1024^2, free / 1024^2
}' >&2
echo "... waiting 20 seconds for you to cancel"
sleep 20
echo
fi
if [ "${TERM:-no_term}" = "${TERM#[Ll]inux}" ]; then
printf "\033]0;${0##*/}: $title\a"
fi
image "$title.iso"
retval=$?
actual_size="$(du -k "$title.iso" |awk '{print $1}')"
# if actual size is 5+ MB smaller than expected size
if [ "$actual_size" -lt "$((size-5*1024))" ]; then
echo "$actual_size $size" |awk '{
printf "WARNING: final size (%.2fG) is %.1fM smaller than expected (%.2fG)",
$1 / 1024 / 1024, ($2 - $1) / 1024, $2 / 1024 / 1024;
}' >&2
exit 2
fi
exit $retval