3 # smartmontools drive database update script
5 # Home page of code is: http://www.smartmontools.org
7 # Copyright (C) 2010-17 Christian Franke
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2, or (at your option)
14 # You should have received a copy of the GNU General Public License
15 # (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
17 # $Id: update-smart-drivedb.in 4584 2017-11-03 22:43:32Z chrfranke $
22 # Set by config.status
23 @ENABLE_SCRIPTPATH_TRUE@
export PATH
="@scriptpath@"
27 exec_prefix
="@exec_prefix@"
29 datarootdir
="@datarootdir@"
31 drivedbdir
="@drivedbdir@"
34 os_dltools
="@os_dltools@"
36 # drivedb.h update branch
37 BRANCH
="@DRIVEDB_BRANCH@"
39 # Default drivedb location
40 DRIVEDB
="$drivedbdir/drivedb.h"
42 # GnuPG used to verify signature (disabled if empty)
45 # Smartctl used for syntax check
46 SMARTCTL
="$sbindir/smartctl"
53 smartmontools $VERSION drive database update script
55 Usage: $myname [OPTIONS] [DESTFILE]
57 -s SMARTCTL Use SMARTCTL for syntax check ('-s -' to disable)
59 -t TOOL Use TOOL for download: $os_dltools
60 [default: first one found in PATH]
61 -u LOCATION Use URL of LOCATION for download:
62 sf (Sourceforge code browser via HTTPS)
63 svn (SVN repository via HTTPS) [default]
64 svni (SVN repository via HTTP)
65 trac (Trac code browser via HTTPS)
66 --trunk Download from SVN trunk (may require '--no-verify')
67 --cacert FILE Use CA certificates from FILE to verify the peer
68 --capath DIR Use CA certificate files from DIR to verify the peer
69 --insecure Don't abort download if certificate verification fails
70 --no-verify Don't verify signature
71 --export-key Print the OpenPGP/GPG public key block
72 --dryrun Print download commands only
76 or DESTFILE from branches/$BRANCH of smartmontools
84 echo "$myname: $*" >&2
90 echo "$myname: (Warning) $*" >&2
96 sf
) url
='https://sourceforge.net/p/smartmontools/code/HEAD/tree/trunk/smartmontools/drivedb.h?format=raw' ;;
97 svn
) url
='https://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' ;;
98 svni
) url
='http://svn.code.sf.net/p/smartmontools/code/trunk/smartmontools/drivedb.h' ;;
99 trac
) url
='https://www.smartmontools.org/export/HEAD/trunk/smartmontools/drivedb.h' ;;
111 test -f "$d/$1" ||
continue
112 test -x "$d/$1" ||
continue
122 test -n "$q" ||
echo "$*"
125 # vrun COMMAND ARGS...
128 if [ -n "$dryrun" ]; then
130 elif [ -n "$q" ]; then
138 # vrun2 OUTFILE COMMAND ARGS...
144 if [ -n "$dryrun" ]; then
148 err
=`"$@" 2>&1 > $f` || rc
=$?
149 if [ -n "$err" ]; then
151 test $rc != 0 || rc
=42
166 vrun curl
${q:+-s} -f --max-redirs 0 \
167 ${cacert:+--cacert "$cacert"} \
168 ${capath:+--capath "$capath"} \
169 ${insecure:+--insecure} \
170 -o "$f" "$u" || rc
=$?
174 vrun wget
$q --max-redirect=0 \
175 ${cacert:+--ca-certificate="$cacert"} \
176 ${capath:+--ca-directory="$capath"} \
177 ${insecure:+--no-check-certificate} \
178 -O "$f" "$u" || rc
=$?
182 test -z "$cacert" || vrun
export SSL_CERT_FILE
="$cacert"
183 test -z "$capath" || vrun
export SSL_CERT_DIR
="$capath"
184 # Check also stderr as lynx does not return != 0 on HTTP error
185 vrun2
"$f" lynx
-stderr -noredir -source "$u" || rc
=$?
190 --non-interactive --no-auth-cache \
191 ${cacert:+--config-option "servers:global:ssl-trust-default-ca=no"} \
192 ${cacert:+--config-option "servers:global:ssl-authority-files=$cacert"} \
193 ${insecure:+--trust-server-cert} \
198 vrun fetch
$q --no-redirect \
199 ${cacert:+--ca-cert "$cacert"} \
200 ${capath:+--ca-path "$capath"} \
201 ${insecure:+--no-verify-hostname} \
202 -o "$f" "$u" || rc
=$?
207 ${cacert:+-S cafile="$cacert"} \
208 ${capath:+-S capath="$capath"} \
209 ${insecure:+-S dont} \
210 -o "$f" "$u" || rc
=$?
213 *) error
"$tool: unknown (internal error)" ;;
218 # check_file FILE FIRST_CHAR MIN_SIZE MAX_SIZE
221 local firstchar f maxsize minsize size
222 test -z "$dryrun" ||
return 0
223 f
=$1; firstchar
=$2; minsize
=$3; maxsize
=$4
226 case `dd if="$f" bs=1 count=1 2>/dev/null` in
228 \
<) echo "HTML error message"; return 1 ;;
229 *) echo "unknown file contents"; return 1 ;;
234 if test "$size" -lt $minsize; then
235 echo "too small file size $size bytes"
238 if test "$size" -gt $maxsize; then
239 echo "too large file size $size bytes"
245 # unexpand_svn_id < INFILE > OUTFILE
248 sed 's,\$''Id'': drivedb\.h [0-9][0-9]* 2[-0-9]* [012][:0-9]*Z [a-z][a-z]* \$,$''Id''$,'
251 # Smartmontools Signing Key (through 2018)
252 # <smartmontools-database@listi.jpberlin.de>
255 -----BEGIN PGP PUBLIC KEY BLOCK-----
257 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
299 -----END PGP PUBLIC KEY BLOCK-----
302 # gpg_verify FILE.asc FILE
305 local gnupgtmp opts out rc
306 opts
="--quiet ${q:+--no-secmem-warnin} --batch --no-tty"
308 # Create temp home dir
309 gnupgtmp
="$tmpdir/.gnupg.$$.tmp"
311 mkdir
"$gnupgtmp" ||
exit 1
312 chmod 0700 "$gnupgtmp"
315 "$GPG" $opts --homedir="$gnupgtmp" --import <<EOF
318 test $?
= 0 ||
exit 1
322 out
=`"$GPG" $opts --homedir="$gnupgtmp" --verify "$1" "$2" </dev/null 2>&1` || rc
=1
329 # mv_all PREFIX OLD NEW
332 mv "${1}${2}" "${1}${3}"
333 mv "${1}${2}.raw" "${1}${3}.raw"
334 mv "${1}${2}.raw.asc" "${1}${3}.raw.asc"
349 while true
; do case $1 in
351 shift; test -n "$1" || usage
356 case $1 in *\
*) usage
;; esac
357 case " $os_dltools " in *\
$1\
*) ;; *) usage
;; esac
361 shift; selecturl
"$1" ;;
373 shift; test -n "$1" || usage
377 shift; test -n "$1" || usage
405 if [ -z "$tool" ]; then
406 # Find download tool in PATH
407 for t
in $os_dltools; do
413 test -n "$tool" || error
"found none of: $os_dltools"
416 test -n "$url" || selecturl
"svn"
418 # Check option compatibility
420 svn
:http
*://svn.code.sf.net
*) ;;
421 svn
:*) error
"'-t svn' requires '-u svn' or '-u svni'" ;;
423 case "$tool:${capath:+set}" in
424 svn
:set) warning
"'--capath' is ignored if '-t svn' is used" ;;
426 case "${insecure:-f}:$url" in
427 t
:http
:*) insecure
= ;;
429 *) error
"'-u svni' requires '--insecure'" ;;
431 case "$tool:$insecure" in
432 lynx
:t
) warning
"'--insecure' is ignored if '-t lynx' is used" ;;
436 if [ "$smtctl" != "-" ]; then
437 "$smtctl" -V >/dev
/null
2>&1 \
438 || error
"$smtctl: not found ('-s -' to ignore)"
442 if [ -z "$no_verify" ]; then
444 || error
"GnuPG is not available ('--no-verify' to ignore)"
445 "$GPG" --version >/dev
/null
2>&1 \
446 || error
"$GPG: not found ('--no-verify' to ignore)"
449 # Use destination directory as temp directory for gpg
450 tmpdir
=`dirname "$DEST"`
453 src
=`echo "$url" | sed "s,/trunk/,/branches/$BRANCH/,"`
454 src_asc
=`echo "$src" | sed "s,/drivedb\.h,/drivedb.h.raw.asc,"`
455 test -z "$trunk" || src
=$url
458 test -n "$dryrun" ||
rm -f "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc"
460 vecho
"Download ${trunk:-branches/$BRANCH}/drivedb.h with $tool"
462 download
"$src" "$DEST.new" || rc
=$?
463 if [ $rc != 0 ]; then
465 error
"${trunk:-$BRANCH}/drivedb.h: download failed ($tool: exit $rc)"
467 if ! errmsg
=`check_file "$DEST.new" '/' 10000 1000000`; then
468 mv "$DEST.new" "$DEST.error"
469 error
"$DEST.error: $errmsg"
472 vecho
"Download branches/$BRANCH/drivedb.h.raw.asc with $tool"
474 download
"$src_asc" "$DEST.new.raw.asc" || rc
=$?
475 if [ $rc != 0 ]; then
476 rm -f "$DEST.new" "$DEST.new.raw.asc"
477 error
"$BRANCH/drivedb.h.raw.asc: download failed ($tool: exit $rc)"
479 if ! errmsg
=`check_file "$DEST.new.raw.asc" '-' 200 2000`; then
481 mv "$DEST.new.raw.asc" "$DEST.error.raw.asc"
482 error
"$DEST.error.raw.asc: $errmsg"
485 test -z "$dryrun" ||
exit 0
487 # Create raw file with unexpanded SVN Id
488 # (This assumes newlines are LF and not CR/LF)
489 unexpand_svn_id
< "$DEST.new" > "$DEST.new.raw"
491 # Adjust timestamps and permissions
492 touch "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc"
493 chmod 0644 "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc"
495 if [ -z "$no_verify" ]; then
497 if ! gpg_verify
"$DEST.new.raw.asc" "$DEST.new.raw"; then
498 mv_all
"$DEST" ".new" ".error"
499 test -n "$trunk" || error
"$DEST.error.raw: *** BAD signature ***"
500 error
"$DEST.error.raw: signature from branch no longer valid ('--no-verify' to ignore)"
504 if [ "$smtctl" != "-" ]; then
506 if ! "$smtctl" -B "$DEST.new" -P showall
>/dev
/null
; then
507 mv_all
"$DEST" ".new" ".error"
508 error
"$DEST.error: rejected by $smtctl, probably no longer compatible"
510 vecho
"$smtctl: syntax OK"
513 # Keep old file if identical, ignore missing Id keyword expansion in new file
514 rm -f "$DEST.lastcheck"
515 if [ -f "$DEST" ]; then
516 if [ -f "$DEST.raw" ] && [ -f "$DEST.raw.asc" ]; then
517 if cmp "$DEST.raw" "$DEST.new.raw" >/dev
/null
2>&1 \
518 && cmp "$DEST.raw.asc" "$DEST.new.raw.asc" >/dev
/null
2>&1 \
519 && { cmp "$DEST" "$DEST.new" >/dev
/null
2>&1 \
520 ||
cmp "$DEST.raw" "$DEST.new" >/dev
/null
2>&1; }
522 rm -f "$DEST.new" "$DEST.new.raw" "$DEST.new.raw.asc"
523 touch "$DEST.lastcheck"
524 echo "$DEST is already up to date"
527 mv_all
"$DEST" "" ".old"
529 mv "$DEST" "$DEST.old"
533 mv_all
"$DEST" ".new" ""
535 echo "$DEST updated from ${trunk:-branches/$BRANCH}${no_verify:+ (NOT VERIFIED)}"