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