1#!/bin/sh 2# 3# $NetBSD: postinstall,v 1.129.2.10 2012/09/30 18:59:53 bouyer Exp $ 4# 5# Copyright (c) 2002-2008 The NetBSD Foundation, Inc. 6# All rights reserved. 7# 8# This code is derived from software contributed to The NetBSD Foundation 9# by Luke Mewburn. 10# 11# Redistribution and use in source and binary forms, with or without 12# modification, are permitted provided that the following conditions 13# are met: 14# 1. Redistributions of source code must retain the above copyright 15# notice, this list of conditions and the following disclaimer. 16# 2. Redistributions in binary form must reproduce the above copyright 17# notice, this list of conditions and the following disclaimer in the 18# documentation and/or other materials provided with the distribution. 19# 20# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30# POSSIBILITY OF SUCH DAMAGE. 31# 32# postinstall 33# Check for or fix configuration changes that occur 34# over time as NetBSD evolves. 35# 36 37# 38# XXX BE SURE TO USE ${DEST_DIR} PREFIX BEFORE ALL REAL FILE OPERATIONS XXX 39# 40 41# 42# checks to add: 43# - sysctl(8) renames (net.inet6.ip6.bindv6only -> net.inet6.ip6.v6only) 44# - de* -> tlp* migration (/etc/ifconfig.de*, $ifconfig_de*, 45# dhclient.conf, ...) ? 46# - support quiet/verbose mode ? 47# - differentiate between failures caused by missing source 48# and real failures 49# - install moduli into usr/share/examples/ssh and use from there? 50# - differentiate between "needs fix" versus "can't fix" issues 51# 52 53# This script is executed as part of a cross build. Allow the build 54# environment to override the locations of some tools. 55: ${AWK:=awk} 56: ${DB:=db} 57: ${GREP:=grep} 58: ${HOST_SH:=sh} 59: ${MAKE:=make} 60: ${PWD_MKDB:=/usr/sbin/pwd_mkdb} 61: ${STAT:=stat} 62 63# 64# helper functions 65# 66 67err() 68{ 69 exitval=$1 70 shift 71 echo 1>&2 "${PROGNAME}: $*" 72 if [ -n "${SCRATCHDIR}" ]; then 73 /bin/rm -rf "${SCRATCHDIR}" 74 fi 75 exit ${exitval} 76} 77 78warn() 79{ 80 echo 1>&2 "${PROGNAME}: $*" 81} 82 83msg() 84{ 85 echo " $*" 86} 87 88mkdtemp() 89{ 90 # Make sure we don't loop forever if mkdir will always fail. 91 [ -d /tmp ] || err 2 /tmp is not a directory 92 [ -w /tmp ] || err 2 /tmp is not writable 93 94 _base="/tmp/_postinstall.$$" 95 _serial=0 96 97 while true; do 98 _dir="${_base}.${_serial}" 99 mkdir -m 0700 "${_dir}" && break 100 _serial=$((${_serial} + 1)) 101 done 102 echo "${_dir}" 103} 104 105# Quote args to make them safe in the shell. 106# Usage: quotedlist="$(shell_quote args...)" 107# 108# After building up a quoted list, use it by evaling it inside 109# double quotes, like this: 110# eval "set -- $quotedlist" 111# or like this: 112# eval "\$command $quotedlist \$filename" 113shell_quote() 114{ 115 local result='' 116 local arg 117 for arg in "$@" ; do 118 # Append a space if necessary 119 result="${result}${result:+ }" 120 # Convert each embedded ' to '\'', 121 # then insert ' at the beginning of the first line, 122 # and append ' at the end of the last line. 123 result="${result}$(printf "%s\n" "$arg" | \ 124 sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/")" 125 done 126 printf "%s\n" "$result" 127} 128 129 130# additem item description 131# Add item to list of supported items to check/fix, 132# which are checked/fixed by default if no item is requested by user. 133# 134additem() 135{ 136 [ $# -eq 2 ] || err 3 "USAGE: additem item description" 137 defaultitems="${defaultitems}${defaultitems:+ }$1" 138 eval desc_$1=\"$2\" 139} 140 141# adddisableditem item description 142# Add item to list of supported items to check/fix, 143# but execute the item only if the user asks for it explicitly. 144# 145adddisableditem() 146{ 147 [ $# -eq 2 ] || err 3 "USAGE: adddisableditem item description" 148 otheritems="${otheritems}${otheritems:+ }$1" 149 eval desc_$1=\"$2\" 150} 151 152# checkdir op dir mode 153# Ensure dir exists, and if not, create it with the appropriate mode. 154# Returns 0 if ok, 1 otherwise. 155# 156check_dir() 157{ 158 [ $# -eq 3 ] || err 3 "USAGE: check_dir op dir mode" 159 _cdop="$1" 160 _cddir="$2" 161 _cdmode="$3" 162 [ -d "${_cddir}" ] && return 0 163 if [ "${_cdop}" = "check" ]; then 164 msg "${_cddir} is not a directory" 165 return 1 166 elif ! mkdir -m "${_cdmode}" "${_cddir}" ; then 167 msg "Can't create missing ${_cddir}" 168 return 1 169 else 170 msg "Missing ${_cddir} created" 171 fi 172 return 0 173} 174 175# check_ids op type file id [...] 176# Check if file of type "users" or "groups" contains the relevant IDs 177# Returns 0 if ok, 1 otherwise. 178# 179check_ids() 180{ 181 [ $# -ge 4 ] || err 3 "USAGE: checks_ids op type file id [...]" 182 _op="$1" 183 _type="$2" 184 _file="$3" 185 shift 3 186 #_ids="$@" 187 188 if [ ! -f "${_file}" ]; then 189 msg "${_file} doesn't exist; can't check for missing ${_type}" 190 return 1 191 fi 192 if [ ! -r "${_file}" ]; then 193 msg "${_file} is not readable; can't check for missing ${_type}" 194 return 1 195 fi 196 _notfixed="" 197 if [ "${_op}" = "fix" ]; then 198 _notfixed="${NOT_FIXED}" 199 fi 200 _missing="$(${AWK} -F: ' 201 BEGIN { 202 for (x = 1; x < ARGC; x++) 203 idlist[ARGV[x]]++ 204 ARGC=1 205 } 206 { 207 found[$1]++ 208 } 209 END { 210 for (id in idlist) { 211 if (! (id in found)) 212 print id 213 } 214 } 215 ' "$@" < "${_file}")" || return 1 216 if [ -n "${_missing}" ]; then 217 msg "Missing ${_type}${_notfixed}:" $(echo ${_missing}) 218 return 1 219 fi 220 return 0 221} 222 223# populate_dir op onlynew src dest mode file [file ...] 224# Perform op ("check" or "fix") on files in src/ against dest/ 225# If op = "check" display missing or changed files, optionally with diffs. 226# If op != "check" copies any missing or changed files. 227# If onlynew evaluates to true, changed files are ignored. 228# Returns 0 if ok, 1 otherwise. 229# 230populate_dir() 231{ 232 [ $# -ge 5 ] || err 3 "USAGE: populate_dir op onlynew src dest mode file [...]" 233 _op="$1" 234 _onlynew="$2" 235 _src="$3" 236 _dest="$4" 237 _mode="$5" 238 shift 5 239 #_files="$@" 240 241 if [ ! -d "${_src}" ]; then 242 msg "${_src} is not a directory; skipping check" 243 return 1 244 fi 245 check_dir "${_op}" "${_dest}" 755 || return 1 246 247 _cmpdir_rv=0 248 for f in "$@"; do 249 fs="${_src}/${f}" 250 fd="${_dest}/${f}" 251 _error="" 252 if [ ! -f "${fd}" ]; then 253 _error="${fd} does not exist" 254 elif ! cmp -s "${fs}" "${fd}" ; then 255 if $_onlynew; then # leave existing ${fd} alone 256 continue; 257 fi 258 _error="${fs} != ${fd}" 259 else 260 continue 261 fi 262 if [ "${_op}" = "check" ]; then 263 msg "${_error}" 264 if [ -n "${DIFF_STYLE}" -a -f "${fd}" ]; then 265 diff -${DIFF_STYLE} ${DIFF_OPT} "${fd}" "${fs}" 266 fi 267 _cmpdir_rv=1 268 elif ! rm -f "${fd}" || 269 ! cp -f "${fs}" "${fd}"; then 270 msg "Can't copy ${fs} to ${fd}" 271 _cmpdir_rv=1 272 elif ! chmod "${_mode}" "${fd}"; then 273 msg "Can't change mode of ${fd} to ${_mode}" 274 _cmpdir_rv=1 275 else 276 msg "Copied ${fs} to ${fd}" 277 fi 278 done 279 return ${_cmpdir_rv} 280} 281 282# compare_dir op src dest mode file [file ...] 283# Perform op ("check" or "fix") on files in src/ against dest/ 284# If op = "check" display missing or changed files, optionally with diffs. 285# If op != "check" copies any missing or changed files. 286# Returns 0 if ok, 1 otherwise. 287# 288compare_dir() 289{ 290 [ $# -ge 4 ] || err 3 "USAGE: compare_dir op src dest mode file [...]" 291 _op="$1" 292 _src="$2" 293 _dest="$3" 294 _mode="$4" 295 shift 4 296 #_files="$@" 297 298 populate_dir "$_op" false "$_src" "$_dest" "$_mode" "$@" 299} 300 301# move_file op src dest -- 302# Check (op == "check") or move (op != "check") from src to dest. 303# Returns 0 if ok, 1 otherwise. 304# 305move_file() 306{ 307 [ $# -eq 3 ] || err 3 "USAGE: move_file op src dest" 308 _fm_op="$1" 309 _fm_src="$2" 310 _fm_dest="$3" 311 312 if [ -f "${_fm_src}" -a ! -f "${_fm_dest}" ]; then 313 if [ "${_fm_op}" = "check" ]; then 314 msg "Move ${_fm_src} to ${_fm_dest}" 315 return 1 316 fi 317 if ! mv "${_fm_src}" "${_fm_dest}"; then 318 msg "Can't move ${_fm_src} to ${_fm_dest}" 319 return 1 320 fi 321 msg "Moved ${_fm_src} to ${_fm_dest}" 322 fi 323 return 0 324} 325 326# rcconf_is_set op name var [verbose] -- 327# Load the rcconf for name, and check if obsolete rc.conf(5) variable 328# var is defined or not. 329# Returns 0 if defined (even to ""), otherwise 1. 330# If verbose != "", print an obsolete warning if the var is defined. 331# 332rcconf_is_set() 333{ 334 [ $# -ge 3 ] || err 3 "USAGE: rcconf_is_set op name var [verbose]" 335 _rcis_op="$1" 336 _rcis_name="$2" 337 _rcis_var="$3" 338 _rcis_verbose="$4" 339 _rcis_notfixed="" 340 if [ "${_rcis_op}" = "fix" ]; then 341 _rcis_notfixed="${NOT_FIXED}" 342 fi 343 ( 344 for f in \ 345 "${DEST_DIR}/etc/rc.conf" \ 346 "${DEST_DIR}/etc/rc.conf.d/${_rcis_name}"; do 347 [ -f "${f}" ] && . "${f}" 348 done 349 eval echo -n \"\${${_rcis_var}}\" 1>&3 350 if eval "[ -n \"\${${_rcis_var}}\" \ 351 -o \"\${${_rcis_var}-UNSET}\" != \"UNSET\" ]"; then 352 if [ -n "${_rcis_verbose}" ]; then 353 msg \ 354 "Obsolete rc.conf(5) variable '\$${_rcis_var}' found.${_rcis_notfixed}" 355 fi 356 exit 0 357 else 358 exit 1 359 fi 360 ) 361} 362 363# rcvar_is_enabled var 364# Check if rcvar is enabled 365# 366rcvar_is_enabled() 367{ 368 [ $# -eq 1 ] || err 3 "USAGE: rcvar_is_enabled var" 369 _rcie_var="$1" 370 ( 371 [ -f "${DEST_DIR}/etc/rc.conf" ] && . "${DEST_DIR}/etc/rc.conf" 372 eval _rcie_val="\${${_rcie_var}}" 373 case $_rcie_val in 374 # "yes", "true", "on", or "1" 375 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 376 exit 0 377 ;; 378 379 *) 380 exit 1 381 ;; 382 esac 383 ) 384} 385 386# find_file_in_dirlist() file message dir1 [...] -- 387# Find which directory file is in, and sets ${dir} to match. 388# Returns 0 if matched, otherwise 1 (and sets ${dir} to ""). 389# 390# Generally, check the directory for the "checking from source" case, 391# and then the directory for the "checking from extracted etc.tgz" case. 392# 393find_file_in_dirlist() 394{ 395 [ $# -ge 3 ] || err 3 "USAGE: find_file_in_dirlist file msg dir1 [...]" 396 397 _file="$1" ; shift 398 _msg="$1" ; shift 399 _dir1st= # first dir in list 400 for dir in "$@"; do 401 : ${_dir1st:="${dir}"} 402 if [ -f "${dir}/${_file}" ]; then 403 if [ "${_dir1st}" != "${dir}" ]; then 404 msg \ 405 "(Checking for ${_msg} from ${dir} instead of ${_dir1st})" 406 fi 407 return 0 408 fi 409 done 410 msg "Can't find source directory for ${_msg}" 411 return 1 412} 413 414# file_exists_exact path 415# Returns true if a file exists in the ${DEST_DIR} whose name 416# is exactly ${path}, interpreted in a case-sensitive way 417# even if the underlying file system is case-insensitive. 418# 419# The path must begin with '/' or './', and is interpreted as 420# being relative to ${DEST_DIR}. 421# 422file_exists_exact() 423{ 424 [ -n "$1" ] || err 3 "USAGE: file_exists_exact path" 425 _path="${1#.}" 426 [ -h "${DEST_DIR}${_path}" ] || \ 427 [ -e "${DEST_DIR}${_path}" ] || return 1 428 while [ "${_path}" != "/" ] ; do 429 _dirname="$(dirname "${_path}" 2>/dev/null)" 430 _basename="$(basename "${_path}" 2>/dev/null)" 431 ls -fa "${DEST_DIR}${_dirname}" 2> /dev/null \ 432 | ${GREP} -F -x "${_basename}" >/dev/null \ 433 || return 1 434 _path="${_dirname}" 435 done 436 return 0 437} 438 439# obsolete_paths op 440# Obsolete the list of paths provided on stdin. 441# Each path is relative to ${DEST_DIR}, and should 442# be an absolute path or start with `./'. 443# 444obsolete_paths() 445{ 446 [ -n "$1" ] || err 3 "USAGE: obsolete_paths fix|check" 447 op="$1" 448 449 failed=0 450 while read ofile; do 451 if ! file_exists_exact "${ofile}"; then 452 continue 453 fi 454 ofile="${DEST_DIR}${ofile#.}" 455 cmd="rm" 456 ftype="file" 457 if [ -h "${ofile}" ]; then 458 ftype="link" 459 elif [ -d "${ofile}" ]; then 460 ftype="directory" 461 cmd="rmdir" 462 fi 463 if [ "${op}" = "check" ]; then 464 msg "Remove obsolete ${ftype} ${ofile}" 465 failed=1 466 elif ! eval "${cmd} \${ofile}"; then 467 msg "Can't remove obsolete ${ftype} ${ofile}" 468 failed=1 469 else 470 msg "Removed obsolete ${ftype} ${ofile}" 471 fi 472 done 473 return ${failed} 474} 475 476# obsolete_libs dir 477# Display the minor/teeny shared libraries in dir that are considered 478# to be obsolete. 479# 480# The implementation supports removing obsolete major libraries 481# if the awk variable AllLibs is set, although there is no way to 482# enable that in the enclosing shell function as this time. 483# 484obsolete_libs() 485{ 486 [ $# -eq 1 ] || err 3 "USAGE: obsolete_libs dir" 487 dir="$1" 488 489 _obsolete_libs "${dir}" 490 _obsolete_libs "/usr/libdata/debug/${dir}" 491} 492 493_obsolete_libs() 494{ 495 dir="$1" 496 497 ( 498 499 if [ ! -e "${DEST_DIR}/${dir}" ] 500 then 501 return 0 502 fi 503 504 cd "${DEST_DIR}/${dir}" || err 2 "can't cd to ${DEST_DIR}/${dir}" 505 echo lib*.so.* \ 506 | tr ' ' '\n' \ 507 | ${AWK} -v LibDir="${dir}/" ' 508#{ 509 510function digit(v, c, n) { return (n <= c) ? v[n] : 0 } 511 512function checklib(results, line, regex) { 513 if (! match(line, regex)) 514 return 515 lib = substr(line, RSTART, RLENGTH) 516 rev = substr($0, RLENGTH+1) 517 if (! (lib in results)) { 518 results[lib] = rev 519 return 520 } 521 orevc = split(results[lib], orev, ".") 522 nrevc = split(rev, nrev, ".") 523 maxc = (orevc > nrevc) ? orevc : nrevc 524 for (i = 1; i <= maxc; i++) { 525 res = digit(orev, orevc, i) - digit(nrev, nrevc, i) 526 if (res < 0) { 527 print LibDir lib results[lib] 528 results[lib] = rev 529 return 530 } else if (res > 0) { 531 print LibDir lib rev 532 return 533 } 534 } 535} 536 537/^lib.*\.so\.[0-9]+\.[0-9]+(\.[0-9]+)?(\.debug)?$/ { 538 if (AllLibs) 539 checklib(minor, $0, "^lib.*\\.so\\.") 540 else 541 checklib(found, $0, "^lib.*\\.so\\.[0-9]+\\.") 542} 543 544/^lib.*\.so\.[0-9]+$/ { 545 if (AllLibs) 546 checklib(major, $0, "^lib.*\\.so\\.") 547} 548 549#}' 550 551 ) 552} 553 554# modify_file op srcfile scratchfile awkprog 555# Apply awkprog to srcfile sending output to scratchfile, and 556# if appropriate replace srcfile with scratchfile. 557# 558modify_file() 559{ 560 [ $# -eq 4 ] || err 3 "USAGE: modify_file op file scratch awkprog" 561 562 _mfop="$1" 563 _mffile="$2" 564 _mfscratch="$3" 565 _mfprog="$4" 566 _mffailed=0 567 568 ${AWK} "${_mfprog}" < "${_mffile}" > "${_mfscratch}" 569 if ! cmp -s "${_mffile}" "${_mfscratch}"; then 570 diff "${_mffile}" "${_mfscratch}" > "${_mfscratch}.diffs" 571 if [ "${_mfop}" = "check" ]; then 572 msg "${_mffile} needs the following changes:" 573 _mffailed=1 574 elif ! rm -f "${_mffile}" || 575 ! cp -f "${_mfscratch}" "${_mffile}"; then 576 msg "${_mffile} changes not applied:" 577 _mffailed=1 578 else 579 msg "${_mffile} changes applied:" 580 fi 581 while read _line; do 582 msg " ${_line}" 583 done < "${_mfscratch}.diffs" 584 fi 585 return ${_mffailed} 586} 587 588 589# contents_owner op directory user group 590# Make sure directory and contents are owned (and group-owned) 591# as specified. 592# 593contents_owner() 594{ 595 [ $# -eq 4 ] || err 3 "USAGE: contents_owner op dir user group" 596 597 _op="$1" 598 _dir="$2" 599 _user="$3" 600 _grp="$4" 601 602 if [ "${_op}" = "check" ]; then 603 if [ ! -z "`find "${_dir}" \( ! -user "${_user}" \) -o \ 604 \( ! -group "${_grp}" \)`" ]; then 605 msg \ 606 "${_dir} and contents not all owned by ${_user}:${_grp}" 607 return 1 608 else 609 return 0 610 fi 611 elif [ "${_op}" = "fix" ]; then 612 find "${_dir}" \( \( ! -user "${_user}" \) -o \ 613 \( ! -group "${_grp}" \) \) -a -print0 \ 614 | xargs -0 chown "${_user}:${_grp}" 615 fi 616} 617 618# get_makevar var [var ...] 619# Retrieve the value of a user-settable system make variable 620get_makevar() 621{ 622 $SOURCEMODE || err 3 "get_makevar must be used in source mode" 623 [ $# -eq 0 ] && err 3 "USAGE: get_makevar var [var ...]" 624 625 for _var in "$@"; do 626 _value="$(echo '.include <bsd.own.mk>' | \ 627 ${MAKE} -f - -V "${_var}")" 628 629 eval ${_var}=\"${_value}\" 630 done 631} 632 633# detect_x11 634# Detect if X11 components should be analysed and set values of 635# relevant variables. 636detect_x11() 637{ 638 if $SOURCEMODE; then 639 get_makevar MKX11 X11ROOTDIR X11SRCDIR 640 else 641 if [ -f "${SRC_DIR}/etc/mtree/set.xetc" ]; then 642 MKX11=yes 643 X11ROOTDIR=/this/value/isnt/used/yet 644 else 645 MKX11=no 646 X11ROOTDIR= 647 fi 648 X11SRCDIR=/nonexistent/xsrc 649 fi 650} 651 652# 653# items 654# ----- 655# 656 657# 658# Bluetooth 659# 660 661additem bluetooth "Bluetooth configuration is up to date" 662do_bluetooth() 663{ 664 [ -n "$1" ] || err 3 "USAGE: do_bluetooth fix|check" 665 op="$1" 666 failed=0 667 668 populate_dir "${op}" true \ 669 "${SRC_DIR}/etc/bluetooth" "${DEST_DIR}/etc/bluetooth" 644 \ 670 hosts protocols btattach.conf btdevctl.conf 671 failed=$(( ${failed} + $? )) 672 673 move_file "${op}" "${DEST_DIR}/var/db/btdev.xml" \ 674 "${DEST_DIR}/var/db/btdevctl.plist" 675 failed=$(( ${failed} + $? )) 676 677 notfixed="" 678 if [ "${op}" = "fix" ]; then 679 notfixed="${NOT_FIXED}" 680 fi 681 for _v in btattach btconfig btdevctl; do 682 if rcvar_is_enabled "${_v}"; then 683 msg \ 684 "${_v} is obsolete in rc.conf(5)${notfixed}: use bluetooth=YES" 685 failed=$(( ${failed} + 1 )) 686 fi 687 done 688 689 return ${failed} 690} 691 692# 693# ddbonpanic 694# 695additem ddbonpanic "verify ddb.onpanic is configured in sysctl.conf" 696do_ddbonpanic() 697{ 698 [ -n "$1" ] || err 3 "USAGE: do_ddbonpanic fix|check" 699 700 if ${GREP} -E '^#*[[:space:]]*ddb\.onpanic[[:space:]]*\??=[[:space:]]*[[:digit:]]+' \ 701 "${DEST_DIR}/etc/sysctl.conf" >/dev/null 2>&1 702 then 703 result=0 704 else 705 if [ "$1" = check ]; then 706 msg \ 707 "The ddb.onpanic behaviour is not explicitly specified in /etc/sysctl.conf" 708 result=1 709 else 710 echo >> "${DEST_DIR}/etc/sysctl.conf" 711 sed < "${SRC_DIR}/etc/sysctl.conf" \ 712 -e '/^ddb\.onpanic/q' | \ 713 sed -e '1,/^$/d' >> \ 714 "${DEST_DIR}/etc/sysctl.conf" 715 result=$? 716 fi 717 fi 718 return ${result} 719} 720 721# 722# defaults 723# 724additem defaults "/etc/defaults/ being up to date" 725do_defaults() 726{ 727 [ -n "$1" ] || err 3 "USAGE: do_defaults fix|check" 728 op="$1" 729 failed=0 730 731 # Except for i386 and amd64, rc.conf(5) should be the same as the 732 # one obtained from a source directory 733 extra_scripts="rc.conf" 734 if [ "$MACHINE" = "i386" -o "$MACHINE" = "amd64" ]; then 735 if $SOURCEMODE; then 736 extra_scripts= # clear 737 738 # Generate and compare the correct rc.conf(5) file 739 mkdir "${SCRATCHDIR}/defaults" 740 741 cat "${SRC_DIR}/etc/defaults/rc.conf" \ 742 "${SRC_DIR}/etc/etc.${MACHINE}/rc.conf.append" \ 743 > "${SCRATCHDIR}/defaults/rc.conf" 744 745 compare_dir "${op}" "${SCRATCHDIR}/defaults" \ 746 "${DEST_DIR}/etc/defaults" \ 747 444 \ 748 "rc.conf" 749 failed=$(( ${failed} + $? )) 750 fi 751 fi 752 753 compare_dir "$op" "${SRC_DIR}/etc/defaults" "${DEST_DIR}/etc/defaults" \ 754 444 \ 755 daily.conf monthly.conf security.conf \ 756 weekly.conf ${extra_scripts} 757 failed=$(( ${failed} + $? )) 758 759 find_file_in_dirlist pf.boot.conf "pf.boot.conf" \ 760 "${SRC_DIR}/usr.sbin/pf/etc/defaults" "${SRC_DIR}/etc/defaults" \ 761 || return 1 762 # ${dir} is set by find_file_in_dirlist() 763 compare_dir "$op" "${dir}" "${DEST_DIR}/etc/defaults" 444 pf.boot.conf 764 failed=$(( ${failed} + $? )) 765 766 return ${failed} 767} 768 769# 770# dhcpcd 771# 772additem dhcpcd "dhcpcd configuration is up to date" 773do_dhcpcd() 774{ 775 [ -n "$1" ] || err 3 "USAGE: do_dhcpcd fix|check" 776 op="$1" 777 failed=0 778 779 find_file_in_dirlist dhcpcd.conf "dhcpcd.conf" \ 780 "${SRC_DIR}/external/bsd/dhcpcd/dist" "${SRC_DIR}/etc" || return 1 781 # ${dir} is set by find_file_in_dirlist() 782 populate_dir "$op" true "${dir}" "${DEST_DIR}/etc" 644 dhcpcd.conf 783 failed=$(( ${failed} + $? )) 784 785 return ${failed} 786} 787 788# 789# envsys 790# 791additem envsys "envsys configuration is up to date" 792do_envsys() 793{ 794 [ -n "$1" ] || err 3 "USAGE: do_envsys fix|check" 795 op="$1" 796 failed=0 797 798 populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 799 envsys.conf 800 failed=$(( ${failed} + $? )) 801 802 populate_dir "$op" true "${SRC_DIR}/etc/powerd/scripts" \ 803 "${DEST_DIR}/etc/powerd/scripts" 555 sensor_battery \ 804 sensor_drive sensor_fan sensor_indicator sensor_power \ 805 sensor_resistance sensor_temperature sensor_voltage 806 failed=$(( ${failed} + $? )) 807 808 return ${failed} 809} 810 811# 812# X11 fontconfig 813# 814additem fontconfig "X11 font configuration is up to date" 815do_fontconfig() 816{ 817 [ -n "$1" ] || err 3 "USAGE: do_fontconfig fix|check" 818 op="$1" 819 failed=0 820 821 if [ -f "${DEST_DIR}/etc/fonts/conf.d/10-unhinted.conf" -a \ 822 -f "${DEST_DIR}/etc/fonts/conf.d/10-autohint.conf" ]; then 823 failed=1 824 fi 825 826 if [ "$failed" = 1 ]; then 827 msg \ 828 "Broken fontconfig configuration found; please delete these files" 829 msg \ 830 "in the ${DESTDIR}/etc/fonts/conf.d/ subdirectory:" 831 msg \ 832 " 10-autohint.conf 10-no-sub-pixel.conf 10-sub-pixel-bgr.conf" 833 msg \ 834 " 10-sub-pixel-rgb.conf 10-sub-pixel-vbgr.conf" 835 msg \ 836 " 10-sub-pixel-vrgb.conf 10-unhinted.conf 25-unhint-nonlatin.conf" 837 msg \ 838 " 65-khmer.conf 70-no-bitmaps.conf 70-yes-bitmaps.conf" 839 msg \ 840 "(This warning only appears if both the 10-unhinted.conf and" 841 msg \ 842 "10-autohint.conf files are present." 843 fi 844 845 return ${failed} 846} 847 848# 849# gid 850# 851additem gid "required groups in /etc/group" 852do_gid() 853{ 854 [ -n "$1" ] || err 3 "USAGE: do_gid fix|check" 855 856 check_ids "$1" groups "${DEST_DIR}/etc/group" \ 857 named ntpd sshd authpf _pflogd _rwhod _proxy _timedc \ 858 _sdpd _httpd _mdnsd _tests _tcpdump _tss 859} 860 861# 862# gpio 863# 864additem gpio "gpio configuration is up to date" 865do_gpio() 866{ 867 [ -n "$1" ] || err 3 "USAGE: do_gpio fix|check" 868 op="$1" 869 failed=0 870 871 populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 872 gpio.conf 873 failed=$(( ${failed} + $? )) 874 875 return ${failed} 876} 877 878# 879# hosts 880# 881additem hosts "/etc/hosts being up to date" 882do_hosts() 883{ 884 [ -n "$1" ] || err 3 "USAGE: do_hosts fix|check" 885 886 modify_file "$1" "${DEST_DIR}/etc/hosts" "${SCRATCHDIR}/hosts" ' 887 /^(127\.0\.0\.1|::1)[ ]+[^\.]*$/ { 888 print $0, "localhost." 889 next 890 } 891 { print } 892 ' 893 return $? 894} 895 896# 897# iscsi 898# 899additem iscsi "/etc/iscsi is populated" 900do_iscsi() 901{ 902 [ -n "$1" ] || err 3 "USAGE: do_iscsi fix|check" 903 904 populate_dir "${op}" true \ 905 "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 600 auths 906 populate_dir "${op}" true \ 907 "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 644 targets 908 return $? 909} 910 911# 912# makedev 913# 914additem makedev "/dev/MAKEDEV being up to date" 915do_makedev() 916{ 917 [ -n "$1" ] || err 3 "USAGE: do_makedev fix|check" 918 failed=0 919 920 if [ -f "${SRC_DIR}/etc/MAKEDEV.tmpl" ]; then 921 # generate MAKEDEV from source if source is available 922 env MACHINE="${MACHINE}" \ 923 MACHINE_ARCH="${MACHINE_ARCH}" \ 924 NETBSDSRCDIR="${SRC_DIR}" \ 925 ${AWK} -f "${SRC_DIR}/etc/MAKEDEV.awk" \ 926 "${SRC_DIR}/etc/MAKEDEV.tmpl" > "${SCRATCHDIR}/MAKEDEV" 927 fi 928 929 find_file_in_dirlist MAKEDEV "MAKEDEV" \ 930 "${SCRATCHDIR}" "${SRC_DIR}/dev" \ 931 || return 1 932 # ${dir} is set by find_file_in_dirlist() 933 compare_dir "$1" "${dir}" "${DEST_DIR}/dev" 555 MAKEDEV 934 failed=$(( ${failed} + $? )) 935 936 find_file_in_dirlist MAKEDEV.local "MAKEDEV.local" \ 937 "${SRC_DIR}/etc" "${SRC_DIR}/dev" \ 938 || return 1 939 # ${dir} is set by find_file_in_dirlist() 940 compare_dir "$1" "${dir}" "${DEST_DIR}/dev" 555 MAKEDEV.local 941 failed=$(( ${failed} + $? )) 942 943 return ${failed} 944} 945 946# 947# motd 948# 949additem motd "contents of motd" 950do_motd() 951{ 952 [ -n "$1" ] || err 3 "USAGE: do_motd fix|check" 953 954 if ${GREP} -i 'http://www.NetBSD.org/Misc/send-pr.html' \ 955 "${DEST_DIR}/etc/motd" >/dev/null 2>&1 \ 956 || ${GREP} -i 'http://www.NetBSD.org/support/send-pr.html' \ 957 "${DEST_DIR}/etc/motd" >/dev/null 2>&1 958 then 959 tmp1="$(mktemp /tmp/postinstall.motd.XXXXXXXX)" 960 tmp2="$(mktemp /tmp/postinstall.motd.XXXXXXXX)" 961 sed '1,2d' <"${SRC_DIR}/etc/motd" >"${tmp1}" 962 sed '1,2d' <"${DEST_DIR}/etc/motd" >"${tmp2}" 963 964 if [ "$1" = check ]; then 965 cmp -s "${tmp1}" "${tmp2}" 966 result=$? 967 if [ "${result}" -ne 0 ]; then 968 msg \ 969 "Bug reporting messages do not seem to match the installed release" 970 fi 971 else 972 head -n 2 "${DEST_DIR}/etc/motd" >"${tmp1}" 973 sed '1,2d' <"${SRC_DIR}/etc/motd" >>"${tmp1}" 974 cp "${tmp1}" "${DEST_DIR}/etc/motd" 975 result=0 976 fi 977 978 rm -f "${tmp1}" "${tmp2}" 979 else 980 result=0 981 fi 982 983 return ${result} 984} 985 986# 987# mtree 988# 989additem mtree "/etc/mtree/ being up to date" 990do_mtree() 991{ 992 [ -n "$1" ] || err 3 "USAGE: do_mtree fix|check" 993 failed=0 994 995 compare_dir "$1" "${SRC_DIR}/etc/mtree" "${DEST_DIR}/etc/mtree" 444 special 996 failed=$(( ${failed} + $? )) 997 998 if ! $SOURCEMODE; then 999 MTREE_DIR="${SRC_DIR}/etc/mtree" 1000 else 1001 ${MAKE} -C ${SRC_DIR}/etc/mtree emit_dist_file > \ 1002 "${SCRATCHDIR}/NetBSD.dist" 1003 MTREE_DIR="${SCRATCHDIR}" 1004 fi 1005 compare_dir "$1" "${MTREE_DIR}" "${DEST_DIR}/etc/mtree" 444 NetBSD.dist 1006 failed=$(( ${failed} + $? )) 1007 1008 return ${failed} 1009} 1010 1011# 1012# named 1013# 1014additem named "named configuration update" 1015do_named() 1016{ 1017 [ -n "$1" ] || err 3 "USAGE: do_named fix|check" 1018 op="$1" 1019 1020 move_file "${op}" \ 1021 "${DEST_DIR}/etc/namedb/named.conf" \ 1022 "${DEST_DIR}/etc/named.conf" 1023 1024 compare_dir "${op}" "${SRC_DIR}/etc/namedb" "${DEST_DIR}/etc/namedb" \ 1025 644 \ 1026 root.cache 1027} 1028 1029# 1030# pam 1031# 1032additem pam "/etc/pam.d is populated" 1033do_pam() 1034{ 1035 [ -n "$1" ] || err 3 "USAGE: do_pam fix|check" 1036 op="$1" 1037 failed=0 1038 1039 populate_dir "${op}" true "${SRC_DIR}/etc/pam.d" \ 1040 "${DEST_DIR}/etc/pam.d" 644 \ 1041 README display_manager ftpd gdm imap kde login other passwd \ 1042 pop3 ppp rexecd rsh sshd su system telnetd xdm xserver 1043 1044 failed=$(( ${failed} + $? )) 1045 1046 return ${failed} 1047} 1048 1049# 1050# periodic 1051# 1052additem periodic "/etc/{daily,weekly,monthly,security} being up to date" 1053do_periodic() 1054{ 1055 [ -n "$1" ] || err 3 "USAGE: do_periodic fix|check" 1056 1057 compare_dir "$1" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1058 daily weekly monthly security 1059} 1060 1061# 1062# pf 1063# 1064additem pf "pf configuration being up to date" 1065do_pf() 1066{ 1067 [ -n "$1" ] || err 3 "USAGE: do_pf fix|check" 1068 op="$1" 1069 failed=0 1070 1071 find_file_in_dirlist pf.os "pf.os" \ 1072 "${SRC_DIR}/dist/pf/etc" "${SRC_DIR}/etc" \ 1073 || return 1 1074 # ${dir} is set by find_file_in_dirlist() 1075 populate_dir "${op}" true \ 1076 "${dir}" "${DEST_DIR}/etc" 644 \ 1077 pf.conf 1078 failed=$(( ${failed} + $? )) 1079 1080 compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 pf.os 1081 failed=$(( ${failed} + $? )) 1082 1083 return ${failed} 1084} 1085 1086# 1087# pwd_mkdb 1088# 1089additem pwd_mkdb "passwd database version" 1090do_pwd_mkdb() 1091{ 1092 [ -n "$1" ] || err 3 "USAGE: do_pwd_mkdb fix|check" 1093 op="$1" 1094 failed=0 1095 1096 # XXX Ideally, we should figure out the endianness of the 1097 # target machine, and add "-E B"/"-E L" to the db(1) flags, 1098 # and "-B"/"-L" to the pwd_mkdb(8) flags if the target is not 1099 # the same as the host machine. It probably doesn't matter, 1100 # because we don't expect "postinstall fix pwd_mkdb" to be 1101 # invoked during a cross build. 1102 1103 set -- $(${DB} -q -Sb -Ub -To -N hash ${DEST_DIR}/etc/pwd.db \ 1104 'VERSION\0') 1105 case "$2" in 1106 '\001\000\000\000') return 0 ;; # version 1, little-endian 1107 '\000\000\000\001') return 0 ;; # version 1, big-endian 1108 esac 1109 1110 if [ "${op}" = "check" ]; then 1111 msg "Update format of passwd database" 1112 failed=1 1113 elif ! ${PWD_MKDB} -V 1 -d ${DEST_DIR:-/} ${DEST_DIR}/etc/master.passwd; then 1114 msg "Can't update format of passwd database" 1115 failed=1 1116 else 1117 msg "Updated format of passwd database" 1118 fi 1119 1120 return ${failed} 1121} 1122 1123# 1124# rc 1125# 1126additem rc "/etc/rc* and /etc/rc.d/ being up to date" 1127do_rc() 1128{ 1129 [ -n "$1" ] || err 3 "USAGE: do_rc fix|check" 1130 op="$1" 1131 failed=0 1132 generated_scripts="" 1133 if [ "${MKX11}" != "no" ]; then 1134 generated_scripts="${generated_scripts} xdm xfs" 1135 fi 1136 1137 compare_dir "${op}" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1138 rc rc.subr rc.shutdown 1139 failed=$(( ${failed} + $? )) 1140 1141 if ! $SOURCEMODE; then 1142 extra_scripts="${generated_scripts}" 1143 else 1144 extra_scripts="" 1145 fi 1146 1147 compare_dir "${op}" "${SRC_DIR}/etc/rc.d" "${DEST_DIR}/etc/rc.d" 555 \ 1148 DAEMON DISKS LOGIN NETWORKING SERVERS \ 1149 accounting altqd amd apmd \ 1150 bluetooth bootconf.sh bootparams \ 1151 ccd cgd cleartmp cron \ 1152 dhclient dhcpcd dhcpd dhcrelay dmesg downinterfaces envsys \ 1153 fsck fsck_root ftp_proxy ftpd \ 1154 gpio \ 1155 hostapd httpd \ 1156 identd ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec \ 1157 irdaattach iscsi_target isdnd isibootd \ 1158 kdc \ 1159 ldconfig local lpd lvm\ 1160 makemandb mdnsd mixerctl mopd motd mountall mountcritlocal \ 1161 mountcritremote mountd moused mrouted \ 1162 named ndbootd network newsyslog nfsd nfslocking npf \ 1163 ntpd ntpdate \ 1164 perusertmp pf pf_boot pflogd postfix powerd ppp pwcheck \ 1165 quota \ 1166 racoon rpcbind raidframe raidframeparity random_seed \ 1167 rarpd rbootd rndctl \ 1168 root route6d routed rtadvd rtclocaltime rtsold rwho \ 1169 savecore screenblank securelevel sshd \ 1170 staticroute swap1 swap2 sysctl sysdb syslogd \ 1171 timed tpctl ttys \ 1172 veriexec virecover wdogctl wpa_supplicant wscons wsmoused \ 1173 ypbind yppasswdd ypserv \ 1174 ${extra_scripts} 1175 failed=$(( ${failed} + $? )) 1176 1177 if $SOURCEMODE && [ -n "${generated_scripts}" ]; then 1178 # generate scripts 1179 mkdir "${SCRATCHDIR}/rc" 1180 for f in ${generated_scripts}; do 1181 sed -e "s,@X11ROOTDIR@,${X11ROOTDIR},g" \ 1182 < "${SRC_DIR}/etc/rc.d/${f}.in" \ 1183 > "${SCRATCHDIR}/rc/${f}" 1184 done 1185 compare_dir "${op}" "${SCRATCHDIR}/rc" \ 1186 "${DEST_DIR}/etc/rc.d" 555 \ 1187 ${generated_scripts} 1188 failed=$(( ${failed} + $? )) 1189 fi 1190 1191 # check for obsolete rc.d files 1192 for f in NETWORK btattach btconfig btcontrol btdevctl bthcid btuartd \ 1193 fsck.sh kerberos nfsiod sdpd servers \ 1194 systemfs daemon gated login poffd portmap sunndd xntpd; do 1195 fd="/etc/rc.d/${f}" 1196 [ -e "${DEST_DIR}${fd}" ] && echo "${fd}" 1197 done | obsolete_paths "${op}" 1198 failed=$(( ${failed} + $? )) 1199 1200 # check for obsolete rc.conf(5) variables 1201 set -- amd amd_master \ 1202 btcontrol btcontrol_devices \ 1203 critical_filesystems critical_filesystems_beforenet \ 1204 mountcritlocal mountcritremote \ 1205 network ip6forwarding \ 1206 network nfsiod_flags \ 1207 sdpd sdpd_control \ 1208 sdpd sdpd_groupname \ 1209 sdpd sdpd_username \ 1210 sysctl defcorename 1211 while [ $# -gt 1 ]; do 1212 if rcconf_is_set "${op}" "$1" "$2" 1; then 1213 failed=1 1214 fi 1215 shift 2 1216 done 1217 1218 return ${failed} 1219} 1220 1221# 1222# sendmail 1223# 1224adddisableditem sendmail "remove obsolete sendmail configuration files and scripts" 1225do_sendmail() 1226{ 1227 [ -n "$1" ] || err 3 "USAGE: do_sendmail fix|check" 1228 op="$1" 1229 failed=0 1230 1231 # Don't complain if the "sendmail" package is installed because the 1232 # files might still be in use. 1233 if /usr/sbin/pkg_info -qe sendmail >/dev/null 2>&1; then 1234 return 0 1235 fi 1236 1237 for f in /etc/mail/helpfile /etc/mail/local-host-names \ 1238 /etc/mail/sendmail.cf /etc/mail/submit.cf /etc/rc.d/sendmail \ 1239 /etc/rc.d/smmsp /usr/share/misc/sendmail.hf \ 1240 $(find ${DEST_DIR}/usr/share/sendmail -type f) \ 1241 $(find ${DEST_DIR}/usr/share/sendmail -type d) \ 1242 ${DEST_DIR}/var/log/sendmail.st \ 1243 ${DEST_DIR}/var/spool/clientmqueue \ 1244 ${DEST_DIR}/var/spool/mqueue; do 1245 [ -e "${DEST_DIR}${f}" ] && echo "${f}" 1246 done | obsolete_paths "${op}" 1247 failed=$(( ${failed} + $? )) 1248 1249 return ${failed} 1250} 1251 1252# 1253# mailerconf 1254# 1255adddisableditem mailerconf "update /etc/mailer.conf after sendmail removal" 1256do_mailerconf() 1257{ 1258 [ -n "$1" ] || err 3 "USAGE: do_mailterconf fix|check" 1259 op="$1" 1260 1261 failed=0 1262 mta_path="$(${AWK} '/^sendmail[ \t]/{print$2}' ${DEST_DIR}/etc/mailer.conf)" 1263 old_sendmail_path="/usr/libexec/sendmail/sendmail" 1264 if [ "${mta_path}" = "${old_sendmail_path}" ]; then 1265 if [ "$op" = check ]; then 1266 msg "mailer.conf points to obsolete ${old_sendmail_path}" 1267 failed=1; 1268 else 1269 populate_dir "${op}" false \ 1270 "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 mailer.conf 1271 failed=$? 1272 fi 1273 fi 1274 1275 return ${failed} 1276} 1277 1278# 1279# ssh 1280# 1281additem ssh "ssh configuration update" 1282do_ssh() 1283{ 1284 [ -n "$1" ] || err 3 "USAGE: do_ssh fix|check" 1285 op="$1" 1286 1287 failed=0 1288 _etcssh="${DEST_DIR}/etc/ssh" 1289 if ! check_dir "${op}" "${_etcssh}" 755; then 1290 failed=1 1291 fi 1292 1293 if [ ${failed} -eq 0 ]; then 1294 for f in \ 1295 ssh_known_hosts ssh_known_hosts2 \ 1296 ssh_host_dsa_key ssh_host_dsa_key.pub \ 1297 ssh_host_rsa_key ssh_host_rsa_key.pub \ 1298 ssh_host_key ssh_host_key.pub \ 1299 ; do 1300 if ! move_file "${op}" \ 1301 "${DEST_DIR}/etc/${f}" "${_etcssh}/${f}" ; then 1302 failed=1 1303 fi 1304 done 1305 for f in sshd.conf ssh.conf ; do 1306 # /etc/ssh/ssh{,d}.conf -> ssh{,d}_config 1307 # 1308 if ! move_file "${op}" \ 1309 "${_etcssh}/${f}" "${_etcssh}/${f%.conf}_config" ; 1310 then 1311 failed=1 1312 fi 1313 # /etc/ssh{,d}.conf -> /etc/ssh/ssh{,d}_config 1314 # 1315 if ! move_file "${op}" \ 1316 "${DEST_DIR}/etc/${f}" \ 1317 "${_etcssh}/${f%.conf}_config" ; 1318 then 1319 failed=1 1320 fi 1321 done 1322 fi 1323 1324 sshdconf="" 1325 for f in \ 1326 "${_etcssh}/sshd_config" \ 1327 "${_etcssh}/sshd.conf" \ 1328 "${DEST_DIR}/etc/sshd.conf" ; do 1329 if [ -f "${f}" ]; then 1330 sshdconf="${f}" 1331 break 1332 fi 1333 done 1334 if [ -n "${sshdconf}" ]; then 1335 modify_file "${op}" "${sshdconf}" "${SCRATCHDIR}/sshdconf" ' 1336 /^[^#$]/ { 1337 kw = tolower($1) 1338 if (kw == "hostkey" && 1339 $2 ~ /^\/etc\/+ssh_host(_[dr]sa)?_key$/ ) { 1340 sub(/\/etc\/+/, "/etc/ssh/") 1341 } 1342 if (kw == "rhostsauthentication" || 1343 kw == "verifyreversemapping" || 1344 kw == "reversemappingcheck") { 1345 sub(/^/, "# DEPRECATED:\t") 1346 } 1347 } 1348 { print } 1349 ' 1350 failed=$(( ${failed} + $? )) 1351 fi 1352 1353 if ! find_file_in_dirlist moduli "moduli" \ 1354 "${SRC_DIR}/crypto/external/bsd/openssh/dist" "${SRC_DIR}/etc" ; then 1355 failed=1 1356 # ${dir} is set by find_file_in_dirlist() 1357 elif ! compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 moduli; then 1358 failed=1 1359 fi 1360 1361 if ! check_dir "${op}" "${DEST_DIR}/var/chroot/sshd" 755 ; then 1362 failed=1 1363 fi 1364 1365 if rcconf_is_set "${op}" sshd sshd_conf_dir 1; then 1366 failed=1 1367 fi 1368 1369 return ${failed} 1370} 1371 1372# 1373# wscons 1374# 1375additem wscons "wscons configuration file update" 1376do_wscons() 1377{ 1378 [ -n "$1" ] || err 3 "USAGE: do_wscons fix|check" 1379 op="$1" 1380 1381 [ -f "${DEST_DIR}/etc/wscons.conf" ] || return 0 1382 1383 failed=0 1384 notfixed="" 1385 if [ "${op}" = "fix" ]; then 1386 notfixed="${NOT_FIXED}" 1387 fi 1388 while read _type _arg1 _rest; do 1389 if [ "${_type}" = "mux" -a "${_arg1}" = "1" ]; then 1390 msg \ 1391 "Obsolete wscons.conf(5) entry \""${_type} ${_arg1}"\" found.${notfixed}" 1392 failed=1 1393 fi 1394 done < "${DEST_DIR}/etc/wscons.conf" 1395 1396 return ${failed} 1397} 1398 1399# 1400# X11 1401# 1402additem x11 "x11 configuration update" 1403do_x11() 1404{ 1405 [ -n "$1" ] || err 3 "USAGE: do_x11 fix|check" 1406 op="$1" 1407 1408 failed=0 1409 _etcx11="${DEST_DIR}/etc/X11" 1410 if [ ! -d "${_etcx11}" ]; then 1411 msg "${_etcx11} is not a directory; skipping check" 1412 return 0 1413 fi 1414 if [ -d "${DEST_DIR}/usr/X11R6/." ] 1415 then 1416 _libx11="${DEST_DIR}/usr/X11R6/lib/X11" 1417 if [ ! -d "${_libx11}" ]; then 1418 msg "${_libx11} is not a directory; skipping check" 1419 return 0 1420 fi 1421 fi 1422 1423 _notfixed="" 1424 if [ "${op}" = "fix" ]; then 1425 _notfixed="${NOT_FIXED}" 1426 fi 1427 1428 for d in \ 1429 fs lbxproxy proxymngr rstart twm xdm xinit xserver xsm \ 1430 ; do 1431 sd="${_libx11}/${d}" 1432 ld="/etc/X11/${d}" 1433 td="${DEST_DIR}${ld}" 1434 if [ -h "${sd}" ]; then 1435 continue 1436 elif [ -d "${sd}" ]; then 1437 tdfiles="$(find "${td}" \! -type d)" 1438 if [ -n "${tdfiles}" ]; then 1439 msg "${sd} exists yet ${td} already" \ 1440 "contains files${_notfixed}" 1441 else 1442 msg "Migrate ${sd} to ${td}${_notfixed}" 1443 fi 1444 failed=1 1445 elif [ -e "${sd}" ]; then 1446 msg "Unexpected file ${sd}${_notfixed}" 1447 continue 1448 else 1449 continue 1450 fi 1451 done 1452 1453 return ${failed} 1454} 1455 1456# 1457# xkb 1458# 1459# /usr/X11R7/lib/X11/xkb/symbols/pc used to be a directory, but changed 1460# to a file on 2009-06-12. Fixing this requires removing the directory 1461# (which we can do) and re-extracting the xbase set (which we can't do), 1462# or at least adding that one file (which we may be able to do if X11SRCDIR 1463# is available). 1464# 1465additem xkb "clean up for xkbdata to xkeyboard-config upgrade" 1466do_xkb() 1467{ 1468 [ -n "$1" ] || err 3 "USAGE: do_xkb fix|check" 1469 op="$1" 1470 failed=0 1471 1472 pcpath="/usr/X11R7/lib/X11/xkb/symbols/pc" 1473 pcsrcdir="${X11SRCDIR}/external/mit/xkeyboard-config/dist/symbols" 1474 1475 filemsg="\ 1476${pcpath} was a directory, should be a file. 1477 To fix, extract the xbase set again." 1478 1479 _notfixed="" 1480 if [ "${op}" = "fix" ]; then 1481 _notfixed="${NOT_FIXED}" 1482 fi 1483 1484 if [ ! -d "${DESTDIR}${pcpath}" ]; then 1485 return 0 1486 fi 1487 1488 # Delete obsolete files in the directory, and the directory 1489 # itself. If the directory contains unexpected extra files 1490 # then it will not be deleted. 1491 ( [ -f "${DEST_DIR}"/var/db/obsolete/xbase ] \ 1492 && sort -ru "${DEST_DIR}"/var/db/obsolete/xbase \ 1493 | ${GREP} -E "^\\.?${pcpath}/" ; 1494 echo "${pcpath}" ) \ 1495 | obsolete_paths "${op}" 1496 failed=$(( ${failed} + $? )) 1497 1498 # If the directory was removed above, then try to replace it with 1499 # a file. 1500 if [ -d "${DESTDIR}${pcpath}" ]; then 1501 msg "${filemsg}${_notfixed}" 1502 failed=$(( ${failed} + 1 )) 1503 else 1504 if ! find_file_in_dirlist pc "${pcpath}" \ 1505 "${pcsrcdir}" "${SRC_DIR}${pcpath%/*}" 1506 then 1507 msg "${filemsg}${_notfixed}" 1508 failed=$(( ${failed} + 1 )) 1509 else 1510 # ${dir} is set by find_file_in_dirlist() 1511 populate_dir "${op}" true \ 1512 "${dir}" "${DEST_DIR}${pcpath%/*}" 444 \ 1513 pc 1514 failed=$(( ${failed} + $? )) 1515 fi 1516 fi 1517 1518 return $failed 1519} 1520 1521# 1522# uid 1523# 1524additem uid "required users in /etc/master.passwd" 1525do_uid() 1526{ 1527 [ -n "$1" ] || err 3 "USAGE: do_uid fix|check" 1528 1529 check_ids "$1" users "${DEST_DIR}/etc/master.passwd" \ 1530 named ntpd postfix sshd _pflogd _rwhod _proxy _timedc \ 1531 _sdpd _httpd _mdnsd _tests _tcpdump _tss 1532} 1533 1534 1535# 1536# varrwho 1537# 1538additem varrwho "required ownership of files in /var/rwho" 1539do_varrwho() 1540{ 1541 [ -n "$1" ] || err 3 "USAGE: do_varrwho fix|check" 1542 1543 contents_owner "$1" "${DEST_DIR}/var/rwho" _rwhod _rwhod 1544} 1545 1546 1547# 1548# tcpdumpchroot 1549# 1550additem tcpdumpchroot "remove /var/chroot/tcpdump/etc/protocols" 1551do_tcpdumpchroot() 1552{ 1553 [ -n "$1" ] || err 3 "USAGE: do_tcpdumpchroot fix|check" 1554 1555 failed=0; 1556 if [ -r ${DEST_DIR}/var/chroot/tcpdump/etc/protocols ]; then 1557 if [ "$1" = "fix" ]; then 1558 rm ${DEST_DIR}/var/chroot/tcpdump/etc/protocols 1559 failed=$(( ${failed} + $? )) 1560 rmdir ${DEST_DIR}/var/chroot/tcpdump/etc 1561 failed=$(( ${failed} + $? )) 1562 else 1563 failed=1 1564 fi 1565 fi 1566 return ${failed} 1567} 1568 1569 1570# 1571# atf 1572# 1573additem atf "install missing atf configuration files and validate them" 1574do_atf() 1575{ 1576 [ -n "$1" ] || err 3 "USAGE: do_atf fix|check" 1577 op="$1" 1578 failed=0 1579 1580 # Ensure atf configuration files are in place. 1581 if find_file_in_dirlist NetBSD.conf "NetBSD.conf" \ 1582 "${SRC_DIR}/external/bsd/atf/etc/atf" \ 1583 "${SRC_DIR}/etc/atf"; then 1584 # ${dir} is set by find_file_in_dirlist() 1585 populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \ 1586 NetBSD.conf common.conf || failed=1 1587 else 1588 failed=1 1589 fi 1590 if find_file_in_dirlist atf-run.hooks "atf-run.hooks" \ 1591 "${SRC_DIR}/external/bsd/atf/dist/atf-run/sample" \ 1592 "${SRC_DIR}/etc/atf"; then 1593 # ${dir} is set by find_file_in_dirlist() 1594 populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \ 1595 atf-run.hooks || failed=1 1596 else 1597 failed=1 1598 fi 1599 1600 # Validate the _atf to _tests user/group renaming. 1601 if [ -f "${DEST_DIR}/etc/atf/common.conf" ]; then 1602 handle_atf_user "${op}" || failed=1 1603 else 1604 failed=1 1605 fi 1606 1607 return ${failed} 1608} 1609 1610handle_atf_user() 1611{ 1612 local op="$1" 1613 local failed=0 1614 1615 local conf="${DEST_DIR}/etc/atf/common.conf" 1616 if grep '[^#]*unprivileged-user[ \t]*=.*_atf' "${conf}" >/dev/null 1617 then 1618 if [ "$1" = "fix" ]; then 1619 sed -e \ 1620 "/[^#]*unprivileged-user[\ t]*=/s/_atf/_tests/" \ 1621 "${conf}" >"${conf}.new" 1622 failed=$(( ${failed} + $? )) 1623 mv "${conf}.new" "${conf}" 1624 failed=$(( ${failed} + $? )) 1625 msg "Set unprivileged-user=_tests in ${conf}" 1626 else 1627 msg "unprivileged-user=_atf in ${conf} should be" \ 1628 "unprivileged-user=_tests" 1629 failed=1 1630 fi 1631 fi 1632 1633 return ${failed} 1634} 1635 1636# 1637# catpages 1638# 1639obsolete_catpages() 1640{ 1641 basedir="$2" 1642 section="$3" 1643 mandir="${basedir}/man${section}" 1644 catdir="${basedir}/cat${section}" 1645 test -d "$mandir" || return 0 1646 test -d "$catdir" || return 0 1647 (cd "$mandir" && find . -type f) | { 1648 failed=0 1649 while read manpage; do 1650 manpage="${manpage#./}" 1651 case "$manpage" in 1652 *.Z) 1653 catname="$catdir/${manpage%.*.Z}.0" 1654 ;; 1655 *.gz) 1656 catname="$catdir/${manpage%.*.gz}.0" 1657 ;; 1658 *) 1659 catname="$catdir/${manpage%.*}.0" 1660 ;; 1661 esac 1662 test -e "$catname" -a "$catname" -ot "$mandir/$manpage" || continue 1663 if [ "$1" = "fix" ]; then 1664 rm "$catname" 1665 failed=$(( ${failed} + $? )) 1666 msg "Removed obsolete cat page $catname" 1667 else 1668 msg "Obsolete cat page $catname" 1669 failed=1 1670 fi 1671 done 1672 exit $failed 1673 } 1674} 1675 1676additem catpages "remove outdated cat pages" 1677do_catpages() 1678{ 1679 failed=0 1680 for manbase in /usr/share/man /usr/X11R6/man /usr/X11R7/man; do 1681 for sec in 1 2 3 4 5 6 7 8 9; do 1682 obsolete_catpages $1 ${DEST_DIR}${manbase} ${sec} 1683 failed=$(( ${failed} + $? )) 1684 if [ "$1" = "fix" ]; then 1685 rmdir ${DEST_DIR}${manbase}/cat${sec}/* 2>/dev/null 1686 rmdir ${DEST_DIR}${manbase}/cat${sec} 2>/dev/null 1687 fi 1688 done 1689 done 1690 return $failed 1691} 1692 1693# 1694# obsolete 1695# (this item is last to allow other items to move obsolete files) 1696# 1697additem obsolete "remove obsolete file sets and minor libraries" 1698do_obsolete() 1699{ 1700 [ -n "$1" ] || err 3 "USAGE: do_obsolete fix|check" 1701 op="$1" 1702 failed=0 1703 1704 sort -ru "${DEST_DIR}"/var/db/obsolete/* | obsolete_paths "${op}" 1705 failed=$(( ${failed} + $? )) 1706 1707 ( 1708 obsolete_libs /lib 1709 obsolete_libs /usr/lib 1710 obsolete_libs /usr/lib/i18n 1711 obsolete_libs /usr/X11R6/lib 1712 obsolete_libs /usr/X11R7/lib 1713 [ "$MACHINE" = "amd64" ] && obsolete_libs /usr/lib/i386 1714 [ "$MACHINE" = "sparc64" ] && obsolete_libs /usr/lib/sparc 1715 ) | obsolete_paths "${op}" 1716 failed=$(( ${failed} + $? )) 1717 1718 return ${failed} 1719} 1720 1721 1722# 1723# ptyfsoldnodes 1724# 1725additem ptyfsoldnodes "remove legacy device nodes when using ptyfs" 1726do_ptyfsoldnodes() 1727{ 1728 [ -n "$1" ] || err 3 "USAGE: do_ptyfsoldnodes fix|check" 1729 _ptyfs_op="$1" 1730 1731 # Check whether ptyfs is in use 1732 failed=0; 1733 if ! ${GREP} -E "^ptyfs" "${DEST_DIR}/etc/fstab" > /dev/null; then 1734 msg "ptyfs is not in use" 1735 return 0 1736 fi 1737 1738 if [ ! -e "${DEST_DIR}/dev/pts" ]; then 1739 msg "ptyfs is not properly configured: missing /dev/pts" 1740 return 1 1741 fi 1742 1743 # Find the device major numbers for the pty master and slave 1744 # devices, by parsing the output from "MAKEDEV -s pty0". 1745 # 1746 # Output from MAKEDEV looks like this: 1747 # ./ttyp0 type=char device=netbsd,5,0 mode=666 gid=0 uid=0 1748 # ./ptyp0 type=char device=netbsd,6,0 mode=666 gid=0 uid=0 1749 # 1750 # Output from awk, used in the eval statement, looks like this: 1751 # maj_ptym=6; maj_ptys=5; 1752 # 1753 eval "$( 1754 ${HOST_SH} "${DEST_DIR}/dev/MAKEDEV" -s pty0 2>/dev/null \ 1755 | ${AWK} '\ 1756 BEGIN { before_re = ".*device=[a-zA-Z]*,"; after_re = ",.*"; } 1757 /ptyp0/ { maj_ptym = gensub(before_re, "", 1, $0); 1758 maj_ptym = gensub(after_re, "", 1, maj_ptym); } 1759 /ttyp0/ { maj_ptys = gensub(before_re, "", 1, $0); 1760 maj_ptys = gensub(after_re, "", 1, maj_ptys); } 1761 END { print "maj_ptym=" maj_ptym "; maj_ptys=" maj_ptys ";"; } 1762 ' 1763 )" 1764 #msg "Major numbers are maj_ptym=${maj_ptym} maj_ptys=${maj_ptys}" 1765 if [ -z "$maj_ptym" ] || [ -z "$maj_ptys" ]; then 1766 msg "Cannot find device major numbers for pty master and slave" 1767 return 1 1768 fi 1769 1770 # look for /dev/[pt]ty[p-zP-T][0-9a-zA-Z], and check that they 1771 # have the expected device major numbers. ttyv* is typically not a 1772 # pty device, but we check it anyway. 1773 # 1774 # The "for d1" loop is intended to avoid overflowing ARG_MAX; 1775 # otherwise we could have used a single glob pattern. 1776 # 1777 # If there are no files that match a particular pattern, 1778 # then stat prints something like: 1779 # stat: /dev/[pt]tyx?: lstat: No such file or directory 1780 # and we ignore it. XXX: We also ignore other error messages. 1781 # 1782 _ptyfs_tmp="$(mktemp /tmp/postinstall.ptyfs.XXXXXXXX)" 1783 for d1 in p q r s t u v w x y z P Q R S T; do 1784 ${STAT} -f "%Hr %N" "${DEST_DIR}/dev/"[pt]ty${d1}? 2>&1 1785 done \ 1786 | while read -r major node ; do 1787 case "$major" in 1788 ${maj_ptym}|${maj_ptys}) echo "$node" ;; 1789 esac 1790 done >"${_ptyfs_tmp}" 1791 1792 _desc="legacy device node" 1793 while read node; do 1794 if [ "${_ptyfs_op}" = "check" ]; then 1795 msg "Remove ${_desc} ${node}" 1796 failed=1 1797 else # "fix" 1798 if rm "${node}"; then 1799 msg "Removed ${_desc} ${node}" 1800 else 1801 warn "Failed to remove ${_desc} ${node}" 1802 failed=1 1803 fi 1804 fi 1805 done < "${_ptyfs_tmp}" 1806 rm "${_ptyfs_tmp}" 1807 1808 return ${failed} 1809} 1810 1811 1812# 1813# end of items 1814# ------------ 1815# 1816 1817 1818usage() 1819{ 1820 cat 1>&2 << _USAGE_ 1821Usage: ${PROGNAME} [-s srcdir] [-d destdir] [-m mach] [-a arch] op [item [...]] 1822 Perform post-installation checks and/or fixes on a system's 1823 configuration files. 1824 If no items are provided, a default set of checks or fixes is applied. 1825 1826 Options: 1827 -s {srcdir|tgzfile|tempdir} 1828 Location of the source files. This may be any 1829 of the following: 1830 * A directory that contains a NetBSD source tree; 1831 * A distribution set file such as "etc.tgz" or 1832 "xetc.tgz". Pass multiple -s options to specify 1833 multiple such files; 1834 * A temporary directory in which one or both of 1835 "etc.tgz" and "xetc.tgz" have been extracted. 1836 [${SRC_DIR:-/}] 1837 -d destdir Destination directory to check. [${DEST_DIR:-/}] 1838 -m mach MACHINE. [${MACHINE}] 1839 -a arch MACHINE_ARCH. [${MACHINE_ARCH}] 1840 1841 Operation may be one of: 1842 help Display this help. 1843 list List available items. 1844 check Perform post-installation checks on items. 1845 diff [diff(1) options ...] 1846 Similar to 'check' but also output difference of files. 1847 fix Apply fixes that 'check' determines need to be applied. 1848 usage Display this usage. 1849_USAGE_ 1850 exit 2 1851} 1852 1853 1854list() 1855{ 1856 echo "Default set of items (to apply if no items are provided by user):" 1857 echo " Item Description" 1858 echo " ---- -----------" 1859 for i in ${defaultitems}; do 1860 eval desc=\"\${desc_${i}}\" 1861 printf " %-12s %s\n" "${i}" "${desc}" 1862 done 1863 echo "Items disabled by default (must be requested explicitly):" 1864 echo " Item Description" 1865 echo " ---- -----------" 1866 for i in ${otheritems}; do 1867 eval desc=\"\${desc_${i}}\" 1868 printf " %-12s %s\n" "${i}" "${desc}" 1869 done 1870 1871} 1872 1873 1874main() 1875{ 1876 TGZLIST= # quoted list list of tgz files 1877 SRC_ARGLIST= # quoted list of one or more "-s" args 1878 SRC_DIR="${SRC_ARG}" # set default value for early usage() 1879 N_SRC_ARGS=0 # number of "-s" args 1880 TGZMODE=false # true if "-s" specifies a tgz file 1881 DIRMODE=false # true if "-s" specified a directory 1882 SOURCEMODE=false # true if "-s" specified a source directory 1883 1884 while getopts s:d:m:a: ch; do 1885 case "${ch}" in 1886 s) 1887 qarg="$(shell_quote "${OPTARG}")" 1888 N_SRC_ARGS=$(( $N_SRC_ARGS + 1 )) 1889 SRC_ARGLIST="${SRC_ARGLIST}${SRC_ARGLIST:+ }-s ${qarg}" 1890 if [ -f "${OPTARG}" ]; then 1891 # arg refers to a *.tgz file. 1892 # This may happen twice, for both 1893 # etc.tgz and xetc.tgz, so we build up a 1894 # quoted list in TGZLIST. 1895 TGZMODE=true 1896 TGZLIST="${TGZLIST}${TGZLIST:+ }${qarg}" 1897 # Note that, when TGZMODE is true, 1898 # SRC_ARG is used only for printing 1899 # human-readable messages. 1900 SRC_ARG="${TGZLIST}" 1901 elif [ -d "${OPTARG}" ]; then 1902 # arg refers to a directory. 1903 # It might be a source directory, or a 1904 # directory where the sets have already 1905 # been extracted. 1906 DIRMODE=true 1907 SRC_ARG="${OPTARG}" 1908 if [ -f "${OPTARG}/etc/Makefile" ]; then 1909 SOURCEMODE=true 1910 fi 1911 elif [ -f "${OPTARG%%:*}" -a -f "${OPTARG##*:}" \ 1912 -a ! -f "${OPTARG}" ] 1913 then 1914 # Backward compatibility: allow arg to refer 1915 # to a colon-separated list of tgz files. 1916 # Remove this after NetBSD-5.0 is released. 1917 cat >&2 <<EOF 1918*** WARNING: The "-s tgzfile1:tgzfile2" option is deprecated. Please use 1919 "-s tgzfile1 -s tgzfile2" in future. 1920EOF 1921 TGZMODE=true 1922 TGZLIST="${TGZLIST}${TGZLIST:+ }$( \ 1923 IFS=: eval shell_quote \${OPTARG} )" 1924 else 1925 err 2 "Invalid argument for -s option" 1926 fi 1927 ;; 1928 d) 1929 DEST_DIR="${OPTARG}" 1930 ;; 1931 m) 1932 MACHINE="${OPTARG}" 1933 ;; 1934 a) 1935 MACHINE_ARCH="${OPTARG}" 1936 ;; 1937 *) 1938 usage 1939 ;; 1940 esac 1941 done 1942 shift $((${OPTIND} - 1)) 1943 [ $# -gt 0 ] || usage 1944 1945 if [ "$N_SRC_ARGS" -gt 1 ] && $DIRMODE; then 1946 err 2 "Multiple -s args are allowed only with tgz files" 1947 fi 1948 if [ "$N_SRC_ARGS" -eq 0 ]; then 1949 # The default SRC_ARG was set elsewhere 1950 DIRMODE=true 1951 SOURCEMODE=true 1952 SRC_ARGLIST="-s $(shell_quote "${SRC_ARG}")" 1953 fi 1954 1955 # 1956 # If '-s' arg or args specified tgz files, extract them 1957 # to a scratch directory. 1958 # 1959 if $TGZMODE; then 1960 ETCTGZDIR="${SCRATCHDIR}/etc.tgz" 1961 echo "Note: Creating temporary directory ${ETCTGZDIR}" 1962 if ! mkdir "${ETCTGZDIR}"; then 1963 err 2 "Can't create ${ETCTGZDIR}" 1964 fi 1965 ( # subshell to localise changes to "$@" 1966 eval "set -- ${TGZLIST}" 1967 for tgz in "$@"; do 1968 echo "Note: Extracting files from ${tgz}" 1969 cat "${tgz}" | ( 1970 cd "${ETCTGZDIR}" && 1971 tar -zxf - 1972 ) || err 2 "Can't extract ${tgz}" 1973 done 1974 ) 1975 SRC_DIR="${ETCTGZDIR}" 1976 else 1977 SRC_DIR="${SRC_ARG}" 1978 fi 1979 1980 [ -d "${SRC_DIR}" ] || err 2 "${SRC_DIR} is not a directory" 1981 [ -d "${DEST_DIR}" ] || err 2 "${DEST_DIR} is not a directory" 1982 [ -n "${MACHINE}" ] || err 2 "\${MACHINE} is not defined" 1983 [ -n "${MACHINE_ARCH}" ] || err 2 "\${MACHINE_ARCH} is not defined" 1984 if ! $SOURCEMODE && ! [ -f "${SRC_DIR}/etc/mtree/set.etc" ]; then 1985 err 2 "Files from the etc.tgz set are missing" 1986 fi 1987 1988 # If directories are /, clear them, so various messages 1989 # don't have leading "//". However, this requires 1990 # the use of ${foo:-/} to display the variables. 1991 # 1992 [ "${SRC_DIR}" = "/" ] && SRC_DIR="" 1993 [ "${DEST_DIR}" = "/" ] && DEST_DIR="" 1994 1995 detect_x11 1996 1997 op="$1" 1998 shift 1999 2000 case "${op}" in 2001 diff) 2002 op=check 2003 DIFF_STYLE=n # default style is RCS 2004 OPTIND=1 2005 while getopts bcenpuw ch; do 2006 case "${ch}" in 2007 c|e|n|u) 2008 if [ "${DIFF_STYLE}" != "n" -a \ 2009 "${DIFF_STYLE}" != "${ch}" ]; then 2010 err 2 "conflicting output style: ${ch}" 2011 fi 2012 DIFF_STYLE="${ch}" 2013 ;; 2014 b|p|w) 2015 DIFF_OPT="${DIFF_OPT} -${ch}" 2016 ;; 2017 *) 2018 err 2 "unknown diff option" 2019 ;; 2020 esac 2021 done 2022 shift $((${OPTIND} - 1)) 2023 ;; 2024 esac 2025 2026 case "${op}" in 2027 2028 usage|help) 2029 usage 2030 ;; 2031 2032 list) 2033 echo "Source directory: ${SRC_DIR:-/}" 2034 echo "Target directory: ${DEST_DIR:-/}" 2035 if $TGZMODE; then 2036 echo " (extracted from: ${SRC_ARG})" 2037 fi 2038 list 2039 ;; 2040 2041 check|fix) 2042 todo="$*" 2043 : ${todo:="${defaultitems}"} 2044 2045 # ensure that all supplied items are valid 2046 # 2047 for i in ${todo}; do 2048 eval desc=\"\${desc_${i}}\" 2049 [ -n "${desc}" ] || err 2 "Unsupported ${op} '"${i}"'" 2050 done 2051 2052 # perform each check/fix 2053 # 2054 echo "Source directory: ${SRC_DIR:-/}" 2055 if $TGZMODE; then 2056 echo " (extracted from: ${SRC_ARG})" 2057 fi 2058 echo "Target directory: ${DEST_DIR:-/}" 2059 items_passed= 2060 items_failed= 2061 for i in ${todo}; do 2062 echo "${i} ${op}:" 2063 ( eval do_${i} ${op} ) 2064 if [ $? -eq 0 ]; then 2065 items_passed="${items_passed} ${i}" 2066 else 2067 items_failed="${items_failed} ${i}" 2068 fi 2069 done 2070 2071 if [ "${op}" = "check" ]; then 2072 plural="checks" 2073 else 2074 plural="fixes" 2075 fi 2076 2077 echo "${PROGNAME} ${plural} passed:${items_passed}" 2078 echo "${PROGNAME} ${plural} failed:${items_failed}" 2079 if [ -n "${items_failed}" ]; then 2080 exitstatus=1; 2081 if [ "${op}" = "check" ]; then 2082 [ "$MACHINE" = "$(uname -m)" ] && m= || m=" -m $MACHINE" 2083 cat <<_Fix_me_ 2084To fix, run: 2085 ${HOST_SH} ${0} ${SRC_ARGLIST} -d ${DEST_DIR:-/}$m fix${items_failed} 2086Note that this may overwrite local changes. 2087_Fix_me_ 2088 fi 2089 fi 2090 2091 ;; 2092 2093 *) 2094 warn "Unknown operation '"${op}"'" 2095 usage 2096 ;; 2097 2098 esac 2099} 2100 2101# defaults 2102# 2103PROGNAME="${0##*/}" 2104SRC_ARG="/usr/src" 2105DEST_DIR="/" 2106: ${MACHINE:="$( uname -m )"} # assume native build if $MACHINE is not set 2107: ${MACHINE_ARCH:="$( uname -p )"}# assume native build if not set 2108 2109DIFF_STYLE= 2110NOT_FIXED=" (FIX MANUALLY)" 2111SCRATCHDIR="$( mkdtemp )" || err 2 "Can't create scratch directory" 2112trap "/bin/rm -rf \"\${SCRATCHDIR}\" ; exit 0" 1 2 3 15 # HUP INT QUIT TERM 2113 2114umask 022 2115exec 3>/dev/null 2116exec 4>/dev/null 2117exitstatus=0 2118 2119main "$@" 2120/bin/rm -rf "${SCRATCHDIR}" 2121exit $exitstatus 2122