1#!/bin/sh 2# 3# $NetBSD: postinstall.in,v 1.51 2022/05/29 10:47:40 andvar Exp $ 4# 5# Copyright (c) 2002-2022 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# NOTE: Be sure to use ${DEST_DIR} prefix before all real file operations. 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# - support quiet/verbose mode ? 46# - differentiate between failures caused by missing source 47# and real failures 48# - install moduli into usr/share/examples/ssh and use from there? 49# - differentiate between "needs fix" versus "can't fix" issues 50# 51 52# This script is executed as part of a cross build. Allow the build 53# environment to override the locations of some tools. 54: ${AWK:=awk} 55: ${DB:=db} 56: ${GREP:=grep} 57: ${HOST_SH:=sh} 58: ${MAKE:=make} 59: ${PWD_MKDB:=/usr/sbin/pwd_mkdb} 60: ${SED:=sed} 61: ${SORT:=sort} 62: ${STAT:=stat} 63 64# 65# helper functions 66# 67 68err() 69{ 70 exitval=$1 71 shift 72 echo 1>&2 "${PROGNAME}: $*" 73 if [ -n "${SCRATCHDIR}" ]; then 74 /bin/rm -rf "${SCRATCHDIR}" 75 fi 76 exit ${exitval} 77} 78 79warn() 80{ 81 echo 1>&2 "${PROGNAME}: $*" 82} 83 84msg() 85{ 86 echo " $*" 87} 88 89mkdtemp() 90{ 91 # Make sure we don't loop forever if mkdir will always fail. 92 [ -d /tmp ] || err 2 /tmp is not a directory 93 [ -w /tmp ] || err 2 /tmp is not writable 94 95 _base="/tmp/_postinstall.$$" 96 _serial=0 97 98 while true; do 99 _dir="${_base}.${_serial}" 100 mkdir -m 0700 "${_dir}" && break 101 _serial=$((${_serial} + 1)) 102 done 103 echo "${_dir}" 104} 105 106# Quote args to make them safe in the shell. 107# Usage: quotedlist="$(shell_quote args...)" 108# 109# After building up a quoted list, use it by evaling it inside 110# double quotes, like this: 111# eval "set -- $quotedlist" 112# or like this: 113# eval "\$command $quotedlist \$filename" 114# 115shell_quote() 116{( 117 local result='' 118 local arg qarg 119 LC_COLLATE=C ; export LC_COLLATE # so [a-zA-Z0-9] works in ASCII 120 for arg in "$@" ; do 121 case "${arg}" in 122 '') 123 qarg="''" 124 ;; 125 *[!-./a-zA-Z0-9]*) 126 # Convert each embedded ' to '\'', 127 # then insert ' at the beginning of the first line, 128 # and append ' at the end of the last line. 129 # Finally, elide unnecessary '' pairs at the 130 # beginning and end of the result and as part of 131 # '\'''\'' sequences that result from multiple 132 # adjacent quotes in he input. 133 qarg="$(printf "%s\n" "$arg" | \ 134 ${SED:-sed} -e "s/'/'\\\\''/g" \ 135 -e "1s/^/'/" -e "\$s/\$/'/" \ 136 -e "1s/^''//" -e "\$s/''\$//" \ 137 -e "s/'''/'/g" 138 )" 139 ;; 140 *) 141 # Arg is not the empty string, and does not contain 142 # any unsafe characters. Leave it unchanged for 143 # readability. 144 qarg="${arg}" 145 ;; 146 esac 147 result="${result}${result:+ }${qarg}" 148 done 149 printf "%s\n" "$result" 150)} 151 152# Convert arg $1 to a basic regular expression (as in sed) 153# that will match the arg. This works by inserting backslashes 154# before characters that are special in basic regular expressions. 155# It also inserts backslashes before the extra characters specified 156# in $2 (which defaults to "/,"). 157# XXX: Does not handle embedded newlines. 158# Usage: regex="$(bre_quote "${string}")" 159bre_quote() 160{ 161 local arg="$1" 162 local extra="${2-/,}" 163 printf "%s\n" "${arg}" | ${SED} -e 's/[][^$.*\\'"${extra}"']/\\&/g' 164} 165 166# unprefix dir 167# Remove any dir prefix from a list of paths on stdin, 168# and write the result to stdout. Useful for converting 169# from ${DEST_DIR}/path to /path. 170# 171unprefix() 172{ 173 [ $# -eq 1 ] || err 3 "USAGE: unprefix dir" 174 local prefix="${1%/}" 175 prefix="$(bre_quote "${prefix}")" 176 177 ${SED} -e "s,^${prefix}/,/," 178} 179 180# additem item description 181# Add item to list of supported items to check/fix, 182# which are checked/fixed by default if no item is requested by user. 183# 184additem() 185{ 186 [ $# -eq 2 ] || err 3 "USAGE: additem item description" 187 defaultitems="${defaultitems}${defaultitems:+ }$1" 188 eval desc_$1=\"\$2\" 189} 190 191# adddisableditem item description 192# Add item to list of supported items to check/fix, 193# but execute the item only if the user asks for it explicitly. 194# 195adddisableditem() 196{ 197 [ $# -eq 2 ] || err 3 "USAGE: adddisableditem item description" 198 otheritems="${otheritems}${otheritems:+ }$1" 199 eval desc_$1=\"\$2\" 200} 201 202# checkdir op dir mode 203# Ensure dir exists, and if not, create it with the appropriate mode. 204# Returns 0 if ok, 1 otherwise. 205# 206check_dir() 207{ 208 [ $# -eq 3 ] || err 3 "USAGE: check_dir op dir mode" 209 _cdop="$1" 210 _cddir="$2" 211 _cdmode="$3" 212 [ -d "${_cddir}" ] && return 0 213 if [ "${_cdop}" = "check" ]; then 214 msg "${_cddir} is not a directory" 215 return 1 216 elif ! mkdir -m "${_cdmode}" "${_cddir}" ; then 217 msg "Can't create missing ${_cddir}" 218 return 1 219 else 220 msg "Missing ${_cddir} created" 221 fi 222 return 0 223} 224 225# check_ids op type file srcfile start id ... 226# Check if file of type "users" or "groups" contains the relevant IDs. 227# Use srcfile as a reference for the expected contents. 228# The specified "id" names should be given in numerical order, 229# with the first name corresponding to numerical value "start", 230# and with the special name "SKIP" being used to mark gaps in the 231# sequence. 232# Returns 0 if ok, 1 otherwise. 233# 234check_ids() 235{ 236 [ $# -ge 6 ] || err 3 "USAGE: checks_ids op type file start srcfile id ..." 237 _op="$1" 238 _type="$2" 239 _file="$3" 240 _srcfile="$4" 241 _start="$5" 242 shift 5 243 #_ids="$@" 244 245 if [ ! -f "${_file}" ]; then 246 msg "${_file} doesn't exist; can't check for missing ${_type}" 247 return 1 248 fi 249 if [ ! -r "${_file}" ]; then 250 msg "${_file} is not readable; can't check for missing ${_type}" 251 return 1 252 fi 253 _notfixed="" 254 if [ "${_op}" = "fix" ]; then 255 _notfixed="${NOT_FIXED}" 256 fi 257 _missing="$(${AWK} -v start=$_start -F: ' 258 BEGIN { 259 for (x = 1; x < ARGC; x++) { 260 if (ARGV[x] == "SKIP") 261 continue; 262 idlist[ARGV[x]]++; 263 value[ARGV[x]] = start + x - 1; 264 } 265 ARGC=1 266 } 267 { 268 found[$1]++ 269 number[$1] = $3 270 } 271 END { 272 for (id in idlist) { 273 if (!(id in found)) 274 printf("%s (missing)\n", id) 275 else if (number[id] != value[id]) 276 printf("%s (%d != %d)\n", id, 277 number[id], value[id]) 278 start++; 279 } 280 } 281 ' "$@" < "${_file}")" || return 1 282 if [ -n "${_missing}" ]; then 283 msg "Error ${_type}${_notfixed}:" $(echo ${_missing}) 284 msg "Use the following as a template:" 285 set -- ${_missing} 286 while [ $# -gt 0 ] 287 do 288 ${GREP} -E "^${1}:" ${_srcfile} 289 shift 2 290 done | sort -t: -k3n 291 msg "and adjust if necessary." 292 return 1 293 fi 294 return 0 295} 296 297# populate_dir op onlynew src dest mode file ... 298# Perform op ("check" or "fix") on files in src/ against dest/ 299# If op = "check" display missing or changed files, optionally with diffs. 300# If op != "check" copies any missing or changed files. 301# If onlynew evaluates to true, changed files are ignored. 302# Returns 0 if ok, 1 otherwise. 303# 304populate_dir() 305{ 306 [ $# -ge 5 ] || err 3 "USAGE: populate_dir op onlynew src dest mode file ..." 307 _op="$1" 308 _onlynew="$2" 309 _src="$3" 310 _dest="$4" 311 _mode="$5" 312 shift 5 313 #_files="$@" 314 315 if [ ! -d "${_src}" ]; then 316 msg "${_src} is not a directory; skipping check" 317 return 1 318 fi 319 check_dir "${_op}" "${_dest}" 755 || return 1 320 321 _cmpdir_rv=0 322 for f in "$@"; do 323 fs="${_src}/${f}" 324 fd="${_dest}/${f}" 325 _error="" 326 if [ ! -f "${fd}" ]; then 327 _error="${fd} does not exist" 328 elif ! cmp -s "${fs}" "${fd}" ; then 329 if $_onlynew; then # leave existing ${fd} alone 330 continue; 331 fi 332 _error="${fs} != ${fd}" 333 else 334 continue 335 fi 336 if [ "${_op}" = "check" ]; then 337 msg "${_error}" 338 if [ -n "${DIFF_STYLE}" -a -f "${fd}" ]; then 339 diff -${DIFF_STYLE} ${DIFF_OPT} "${fd}" "${fs}" 340 fi 341 _cmpdir_rv=1 342 elif ! rm -f "${fd}" || 343 ! cp -f "${fs}" "${fd}"; then 344 msg "Can't copy ${fs} to ${fd}" 345 _cmpdir_rv=1 346 elif ! chmod "${_mode}" "${fd}"; then 347 msg "Can't change mode of ${fd} to ${_mode}" 348 _cmpdir_rv=1 349 else 350 msg "Copied ${fs} to ${fd}" 351 fi 352 done 353 return ${_cmpdir_rv} 354} 355 356# compare_dir op src dest mode file ... 357# Perform op ("check" or "fix") on files in src/ against dest/ 358# If op = "check" display missing or changed files, optionally with diffs. 359# If op != "check" copies any missing or changed files. 360# Returns 0 if ok, 1 otherwise. 361# 362compare_dir() 363{ 364 [ $# -ge 4 ] || err 3 "USAGE: compare_dir op src dest mode file ..." 365 _op="$1" 366 _src="$2" 367 _dest="$3" 368 _mode="$4" 369 shift 4 370 #_files="$@" 371 372 populate_dir "$_op" false "$_src" "$_dest" "$_mode" "$@" 373} 374 375# move_file op src dest -- 376# Check (op == "check") or move (op != "check") from src to dest. 377# Returns 0 if ok, 1 otherwise. 378# 379move_file() 380{ 381 [ $# -eq 3 ] || err 3 "USAGE: move_file op src dest" 382 _fm_op="$1" 383 _fm_src="$2" 384 _fm_dest="$3" 385 386 if [ -f "${_fm_src}" -a ! -f "${_fm_dest}" ]; then 387 if [ "${_fm_op}" = "check" ]; then 388 msg "Move ${_fm_src} to ${_fm_dest}" 389 return 1 390 fi 391 if ! mv "${_fm_src}" "${_fm_dest}"; then 392 msg "Can't move ${_fm_src} to ${_fm_dest}" 393 return 1 394 fi 395 msg "Moved ${_fm_src} to ${_fm_dest}" 396 fi 397 return 0 398} 399 400# rcconf_is_set op name var [verbose] -- 401# Load the rcconf for name, and check if obsolete rc.conf(5) variable 402# var is defined or not. 403# Returns 0 if defined (even to ""), otherwise 1. 404# If verbose != "", print an obsolete warning if the var is defined. 405# 406rcconf_is_set() 407{ 408 [ $# -ge 3 ] || err 3 "USAGE: rcconf_is_set op name var [verbose]" 409 _rcis_op="$1" 410 _rcis_name="$2" 411 _rcis_var="$3" 412 _rcis_verbose="$4" 413 _rcis_notfixed="" 414 if [ "${_rcis_op}" = "fix" ]; then 415 _rcis_notfixed="${NOT_FIXED}" 416 fi 417 ( 418 for f in \ 419 "${DEST_DIR}/etc/rc.conf" \ 420 "${DEST_DIR}/etc/rc.conf.d/${_rcis_name}"; do 421 [ -f "${f}" ] && . "${f}" 422 done 423 eval echo -n \"\${${_rcis_var}}\" 1>&3 424 if eval "[ -n \"\${${_rcis_var}}\" \ 425 -o \"\${${_rcis_var}-UNSET}\" != \"UNSET\" ]"; then 426 if [ -n "${_rcis_verbose}" ]; then 427 msg \ 428 "Obsolete rc.conf(5) variable '\$${_rcis_var}' found.${_rcis_notfixed}" 429 fi 430 exit 0 431 else 432 exit 1 433 fi 434 ) 435} 436 437# rcvar_is_enabled var 438# Check if rcvar is enabled 439# 440rcvar_is_enabled() 441{ 442 [ $# -eq 1 ] || err 3 "USAGE: rcvar_is_enabled var" 443 _rcie_var="$1" 444 ( 445 [ -f "${DEST_DIR}/etc/rc.conf" ] && . "${DEST_DIR}/etc/rc.conf" 446 eval _rcie_val=\"\${${_rcie_var}}\" 447 case $_rcie_val in 448 # "yes", "true", "on", or "1" 449 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 450 exit 0 451 ;; 452 453 *) 454 exit 1 455 ;; 456 esac 457 ) 458} 459 460# find_file_in_dirlist() file message dir1 ... -- 461# Find which directory file is in, and sets ${dir} to match. 462# Returns 0 if matched, otherwise 1 (and sets ${dir} to ""). 463# 464# Generally, check the directory for the "checking from source" case, 465# and then the directory for the "checking from extracted etc.tgz" case. 466# 467find_file_in_dirlist() 468{ 469 [ $# -ge 3 ] || err 3 "USAGE: find_file_in_dirlist file msg dir1 ..." 470 471 _file="$1" ; shift 472 _msg="$1" ; shift 473 _dir1st= # first dir in list 474 for dir in "$@"; do 475 : ${_dir1st:="${dir}"} 476 if [ -f "${dir}/${_file}" ]; then 477 if [ "${_dir1st}" != "${dir}" ]; then 478 msg \ 479 "(Checking for ${_msg} from ${dir} instead of ${_dir1st})" 480 fi 481 return 0 482 fi 483 done 484 msg "Can't find source directory for ${_msg}" 485 return 1 486} 487 488# file_exists_exact path 489# Returns true if a file exists in the ${DEST_DIR} whose name 490# is exactly ${path}, interpreted in a case-sensitive way 491# even if the underlying file system is case-insensitive. 492# 493# The path must begin with '/' or './', and is interpreted as 494# being relative to ${DEST_DIR}. 495# 496file_exists_exact() 497{ 498 [ -n "$1" ] || err 3 "USAGE: file_exists_exact path" 499 _path="${1#.}" 500 [ -h "${DEST_DIR}${_path}" ] || \ 501 [ -e "${DEST_DIR}${_path}" ] || return 1 502 while [ "${_path}" != "/" -a "${_path}" != "." ] ; do 503 _dirname="$(dirname "${_path}" 2>/dev/null)" 504 _basename="$(basename "${_path}" 2>/dev/null)" 505 ls -fa "${DEST_DIR}${_dirname}" 2> /dev/null \ 506 | ${GREP} -F -x "${_basename}" >/dev/null \ 507 || return 1 508 _path="${_dirname}" 509 done 510 return 0 511} 512 513# obsolete_paths op 514# Obsolete the list of paths provided on stdin. 515# Each path should start with '/' or './', and 516# will be interpreted relative to ${DEST_DIR}. 517# 518obsolete_paths() 519{ 520 [ -n "$1" ] || err 3 "USAGE: obsolete_paths fix|check" 521 op="$1" 522 523 failed=0 524 while read ofile; do 525 if ! ${file_exists_exact} "${ofile}"; then 526 continue 527 fi 528 ofile="${DEST_DIR}${ofile#.}" 529 cmd="rm" 530 ftype="file" 531 if [ -h "${ofile}" ]; then 532 ftype="link" 533 elif [ -d "${ofile}" ]; then 534 ftype="directory" 535 cmd="rmdir" 536 elif [ ! -e "${ofile}" ]; then 537 continue 538 fi 539 if [ "${op}" = "check" ]; then 540 msg "Remove obsolete ${ftype} ${ofile}" 541 failed=1 542 elif ! eval "${cmd} \"\${ofile}\""; then 543 msg "Can't remove obsolete ${ftype} ${ofile}" 544 failed=1 545 else 546 msg "Removed obsolete ${ftype} ${ofile}" 547 fi 548 done 549 return ${failed} 550} 551 552# obsolete_libs dir 553# Display the minor/teeny shared libraries in dir that are considered 554# to be obsolete. 555# 556# The implementation supports removing obsolete major libraries 557# if the awk variable AllLibs is set, although there is no way to 558# enable that in the enclosing shell function as this time. 559# 560obsolete_libs() 561{ 562 [ $# -eq 1 ] || err 3 "USAGE: obsolete_libs dir" 563 dir="$1" 564 565 _obsolete_libs "${dir}" 566 _obsolete_libs "/usr/libdata/debug/${dir}" 567} 568 569exclude() 570{ 571 local dollar 572 case "$1" in 573 -t) 574 dollar='$' 575 shift 576 ;; 577 *) 578 dollar= 579 ;; 580 esac 581 if [ -z "$*" ]; then 582 cat 583 else 584 eval ${GREP} -v -E "'(^$(echo $* | \ 585 ${SED} -e s/\\./\\\\./g -e 's/ /'${dollar}'|^/'g)${dollar})'" 586 fi 587} 588 589# 590# find all the target symlinks of shared libraries and exclude them 591# from consideration for removal 592# 593exclude_libs() 594{ 595 local target="$(ls -l -d lib*.so.* 2> /dev/null \ 596 | ${AWK} '{ print $11; }' \ 597 | ${SED} -e 's@.*/@@' | ${SORT} -u)" 598 exclude -t ${target} 599} 600 601_obsolete_libs() 602{ 603 dir="$1" 604 605 ( 606 607 if [ ! -e "${DEST_DIR}/${dir}" ] 608 then 609 return 0 610 fi 611 612 cd "${DEST_DIR}/${dir}" || err 2 "can't cd to ${DEST_DIR}/${dir}" 613 echo lib*.so.* \ 614 | tr ' ' '\n' \ 615 | ${AWK} -v LibDir="${dir}/" ' 616#{ 617 618function digit(v, c, n) { return (n <= c) ? v[n] : 0 } 619 620function checklib(results, line, regex) { 621 if (! match(line, regex)) 622 return 623 lib = substr(line, RSTART, RLENGTH) 624 rev = substr($0, RLENGTH+1) 625 if (! (lib in results)) { 626 results[lib] = rev 627 return 628 } 629 orevc = split(results[lib], orev, ".") 630 nrevc = split(rev, nrev, ".") 631 maxc = (orevc > nrevc) ? orevc : nrevc 632 for (i = 1; i <= maxc; i++) { 633 res = digit(orev, orevc, i) - digit(nrev, nrevc, i) 634 if (res < 0) { 635 print LibDir lib results[lib] 636 results[lib] = rev 637 return 638 } else if (res > 0) { 639 print LibDir lib rev 640 return 641 } 642 } 643} 644 645/^lib.*\.so\.[0-9]+\.[0-9]+(\.[0-9]+)?(\.debug)?$/ { 646 if (AllLibs) 647 checklib(minor, $0, "^lib.*\\.so\\.") 648 else 649 checklib(found, $0, "^lib.*\\.so\\.[0-9]+\\.") 650} 651 652/^lib.*\.so\.[0-9]+$/ { 653 if (AllLibs) 654 checklib(major, $0, "^lib.*\\.so\\.") 655} 656 657#}' | exclude_libs 658 659 ) 660} 661 662# obsolete_stand dir 663# Prints the names of all obsolete files and subdirs below the 664# provided dir. dir should be something like /stand/${MACHINE}. 665# The input dir and all output paths are interpreted 666# relative to ${DEST_DIR}. 667# 668# Assumes that the numerically largest subdir is current, and all 669# others are obsolete. 670# 671obsolete_stand() 672{ 673 [ $# -eq 1 ] || err 3 "USAGE: obsolete_stand dir" 674 local dir="$1" 675 local subdir 676 677 if ! [ -d "${DEST_DIR}${dir}" ]; then 678 msg "${DEST_DIR}${dir} doesn't exist; can't check for obsolete files" 679 return 1 680 fi 681 682 ( cd "${DEST_DIR}${dir}" && ls -1d [0-9]*[0-9]/. ) \ 683 | ${GREP} -v '[^0-9./]' \ 684 | sort -t. -r -n -k1,1 -k2,2 -k3,3 \ 685 | tail -n +2 \ 686 | while read subdir ; do 687 subdir="${subdir%/.}" 688 find "${DEST_DIR}${dir}/${subdir}" -depth -print 689 done \ 690 | unprefix "${DEST_DIR}" 691} 692 693# modify_file op srcfile scratchfile awkprog 694# Apply awkprog to srcfile sending output to scratchfile, and 695# if appropriate replace srcfile with scratchfile. 696# 697modify_file() 698{ 699 [ $# -eq 4 ] || err 3 "USAGE: modify_file op file scratch awkprog" 700 701 _mfop="$1" 702 _mffile="$2" 703 _mfscratch="$3" 704 _mfprog="$4" 705 _mffailed=0 706 707 ${AWK} "${_mfprog}" < "${_mffile}" > "${_mfscratch}" 708 if ! cmp -s "${_mffile}" "${_mfscratch}"; then 709 diff "${_mffile}" "${_mfscratch}" > "${_mfscratch}.diffs" 710 if [ "${_mfop}" = "check" ]; then 711 msg "${_mffile} needs the following changes:" 712 _mffailed=1 713 elif ! rm -f "${_mffile}" || 714 ! cp -f "${_mfscratch}" "${_mffile}"; then 715 msg "${_mffile} changes not applied:" 716 _mffailed=1 717 else 718 msg "${_mffile} changes applied:" 719 fi 720 while read _line; do 721 msg " ${_line}" 722 done < "${_mfscratch}.diffs" 723 fi 724 return ${_mffailed} 725} 726 727 728# contents_owner op directory user group 729# Make sure directory and contents are owned (and group-owned) 730# as specified. 731# 732contents_owner() 733{ 734 [ $# -eq 4 ] || err 3 "USAGE: contents_owner op dir user group" 735 736 _op="$1" 737 _dir="$2" 738 _user="$3" 739 _grp="$4" 740 741 if [ "${_op}" = "check" ]; then 742 _files=$(find "${_dir}" \( \( ! -user "${_user}" \) -o \ 743 \( ! -group "${_grp}" \) \) ) 744 _error=$? 745 if [ ! -z "$_files" ] || [ $_error != 0 ]; then 746 msg "${_dir} and contents not all owned by" \ 747 "${_user}:${_grp}" 748 return 1 749 else 750 return 0 751 fi 752 elif [ "${_op}" = "fix" ]; then 753 find "${_dir}" \( \( ! -user "${_user}" \) -o \ 754 \( ! -group "${_grp}" \) \) \ 755 -exec chown "${_user}:${_grp}" -- {} \; 756 fi 757} 758 759# get_makevar var ... 760# Retrieve the value of a user-settable system make variable 761get_makevar() 762{ 763 $SOURCEMODE || err 3 "get_makevar must be used in source mode" 764 [ $# -eq 0 ] && err 3 "USAGE: get_makevar var ..." 765 766 for _var in "$@"; do 767 _value="$(echo '.include <bsd.own.mk>' | \ 768 ${MAKE} -f - -V "\${${_var}}")" 769 770 eval ${_var}=\"\${_value}\" 771 done 772} 773 774# detect_x11 775# Detect if X11 components should be analysed and set values of 776# relevant variables. 777detect_x11() 778{ 779 if $SOURCEMODE; then 780 get_makevar MKX11 X11ROOTDIR X11SRCDIR 781 else 782 if [ -f "${SRC_DIR}/etc/mtree/set.xetc" ]; then 783 MKX11=yes 784 X11ROOTDIR=/this/value/isnt/used/yet 785 else 786 MKX11=no 787 X11ROOTDIR= 788 fi 789 X11SRCDIR=/nonexistent/xsrc 790 fi 791} 792 793# 794# find out where MAKEDEV lives, set MAKEDEV_DIR appropriately 795# 796find_makedev() 797{ 798 if [ -e "${DEST_DIR}/dev/MAKEDEV" ]; then 799 MAKEDEV_DIR="${DEST_DIR}/dev" 800 elif [ -e "${DEST_DIR}/etc/MAKEDEV" ]; then 801 MAKEDEV_DIR="${DEST_DIR}/etc" 802 else 803 MAKEDEV_DIR="${DEST_DIR}/dev" 804 fi 805} 806 807 808# 809# items 810# ----- 811# 812# NOTE: Keep these items sorted, except for obsolete* which are listed last. 813# 814 815# 816# atf 817# 818 819handle_atf_user() 820{ 821 local op="$1" 822 local failed=0 823 824 local conf="${DEST_DIR}/etc/atf/common.conf" 825 if grep '[^#]*unprivileged-user[ \t]*=.*_atf' "${conf}" >/dev/null 826 then 827 if [ "$1" = "fix" ]; then 828 ${SED} -e \ 829 "/[^#]*unprivileged-user[\ t]*=/s/_atf/_tests/" \ 830 "${conf}" >"${conf}.new" 831 failed=$(( ${failed} + $? )) 832 mv "${conf}.new" "${conf}" 833 failed=$(( ${failed} + $? )) 834 msg "Set unprivileged-user=_tests in ${conf}" 835 else 836 msg "unprivileged-user=_atf in ${conf} should be" \ 837 "unprivileged-user=_tests" 838 failed=1 839 fi 840 fi 841 842 return ${failed} 843} 844 845additem atf "install missing atf configuration files and validate them" 846do_atf() 847{ 848 [ -n "$1" ] || err 3 "USAGE: do_atf fix|check" 849 op="$1" 850 failed=0 851 852 # Ensure atf configuration files are in place. 853 if find_file_in_dirlist NetBSD.conf "NetBSD.conf" \ 854 "${SRC_DIR}/external/bsd/atf/etc/atf" \ 855 "${SRC_DIR}/etc/atf"; then 856 # ${dir} is set by find_file_in_dirlist() 857 populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \ 858 NetBSD.conf common.conf || failed=1 859 else 860 failed=1 861 fi 862 if find_file_in_dirlist atf-run.hooks "atf-run.hooks" \ 863 "${SRC_DIR}/external/bsd/atf/dist/tools/sample" \ 864 "${SRC_DIR}/etc/atf"; then 865 # ${dir} is set by find_file_in_dirlist() 866 populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \ 867 atf-run.hooks || failed=1 868 else 869 failed=1 870 fi 871 872 # Validate the _atf to _tests user/group renaming. 873 if [ -f "${DEST_DIR}/etc/atf/common.conf" ]; then 874 handle_atf_user "${op}" || failed=1 875 else 876 failed=1 877 fi 878 879 return ${failed} 880} 881 882 883# 884# autofsconfig 885# 886 887additem autofsconfig "automounter configuration files" 888do_autofsconfig() 889{ 890 [ -n "$1" ] || err 3 "USAGE: do_autofsconfig fix|check" 891 local autofs_files=" 892include_ldap 893include_nis 894special_hosts 895special_media 896special_noauto 897special_null 898" 899 op="$1" 900 failed=0 901 if [ "$op" = "fix" ]; then 902 mkdir -p "${DEST_DIR}/etc/autofs" 903 fi 904 failed=$(( ${failed} + $? )) 905 populate_dir "$op" true "${SRC_DIR}/etc" \ 906 "${DEST_DIR}/etc" \ 907 644 \ 908 auto_master 909 failed=$(( ${failed} + $? )) 910 populate_dir "$op" true "${SRC_DIR}/etc/autofs" \ 911 "${DEST_DIR}/etc/autofs" \ 912 644 \ 913 ${autofs_files} 914 return ${failed} 915} 916 917 918# 919# blocklist 920# 921 922fixblock() 923{ 924 local op="$1" 925 local target="${DEST_DIR}$2" 926 927 if [ ! -f "${target}" ]; then 928 continue 929 fi 930 931 if ${GREP} '[bB]lack' "${target}" > /dev/null; then 932 if [ "$1" = "check" ]; then 933 msg "Fix old configuration file(s)." 934 return 1 935 else 936 local p=$(${STAT} -f %Lp "${target}") 937 chmod u+w "${target}" || return 1 938 if [ "$2" = "/etc/npf.conf" ]; then 939 ${SED} -i -e 's/"blacklistd"/"blocklistd"/g' "${target}" 940 else 941 ${SED} -i -e 's/\([bB]\)lacklist/\1locklist/g' "${target}" 942 fi 943 chmod "${p}" "${target}" 944 fi 945 fi 946} 947 948additem blocklist "rename old files to blocklist" 949do_blocklist() 950{ 951 [ -n "$1" ] || err 3 "USAGE: do_blocklist fix|check" 952 local op="$1" 953 954 # if we are actually using blocklistd 955 for i in /var/db/blacklist.db /etc/blacklistd.conf; do 956 local old="${DEST_DIR}${i}" 957 if [ ! -f "${old}" ]; then 958 continue 959 elif [ "$1" = "check" ]; then 960 msg "Rename old file(s)." 961 return 1 962 fi 963 local new=$(echo "${old}" | ${SED} s/black/block/) 964 mv "${old}" "${new}" || return 1 965 done 966 967 for i in /etc/rc.conf /etc/npf.conf /etc/blocklistd.conf \ 968 /etc/defaults/rc.conf; do 969 fixblock "${op}" "${i}" || return 1 970 done 971} 972 973 974# 975# bluetooth 976# 977 978additem bluetooth "Bluetooth configuration is up to date" 979do_bluetooth() 980{ 981 [ -n "$1" ] || err 3 "USAGE: do_bluetooth fix|check" 982 op="$1" 983 failed=0 984 985 populate_dir "${op}" true \ 986 "${SRC_DIR}/etc/bluetooth" "${DEST_DIR}/etc/bluetooth" 644 \ 987 hosts protocols btattach.conf btdevctl.conf 988 failed=$(( ${failed} + $? )) 989 990 move_file "${op}" "${DEST_DIR}/var/db/btdev.xml" \ 991 "${DEST_DIR}/var/db/btdevctl.plist" 992 failed=$(( ${failed} + $? )) 993 994 notfixed="" 995 if [ "${op}" = "fix" ]; then 996 notfixed="${NOT_FIXED}" 997 fi 998 for _v in btattach btconfig btdevctl; do 999 if rcvar_is_enabled "${_v}"; then 1000 msg \ 1001 "${_v} is obsolete in rc.conf(5)${notfixed}: use bluetooth=YES" 1002 failed=$(( ${failed} + 1 )) 1003 fi 1004 done 1005 1006 return ${failed} 1007} 1008 1009 1010# 1011# catpages 1012# 1013 1014obsolete_catpages() 1015{ 1016 basedir="$2" 1017 section="$3" 1018 mandir="${basedir}/man${section}" 1019 catdir="${basedir}/cat${section}" 1020 test -d "$mandir" || return 0 1021 test -d "$catdir" || return 0 1022 (cd "$mandir" && find . -type f) | { 1023 failed=0 1024 while read manpage; do 1025 manpage="${manpage#./}" 1026 case "$manpage" in 1027 *.Z) 1028 catname="$catdir/${manpage%.*.Z}.0" 1029 ;; 1030 *.gz) 1031 catname="$catdir/${manpage%.*.gz}.0" 1032 ;; 1033 *) 1034 catname="$catdir/${manpage%.*}.0" 1035 ;; 1036 esac 1037 test -e "$catname" -a "$catname" -ot "$mandir/$manpage" || continue 1038 if [ "$1" = "fix" ]; then 1039 rm "$catname" 1040 failed=$(( ${failed} + $? )) 1041 msg "Removed obsolete cat page $catname" 1042 else 1043 msg "Obsolete cat page $catname" 1044 failed=1 1045 fi 1046 done 1047 exit $failed 1048 } 1049} 1050 1051additem catpages "remove outdated cat pages" 1052do_catpages() 1053{ 1054 failed=0 1055 for manbase in /usr/share/man /usr/X11R6/man /usr/X11R7/man; do 1056 for sec in 1 2 3 4 5 6 7 8 9; do 1057 obsolete_catpages "$1" "${DEST_DIR}${manbase}" "${sec}" 1058 failed=$(( ${failed} + $? )) 1059 if [ "$1" = "fix" ]; then 1060 rmdir "${DEST_DIR}${manbase}/cat${sec}"/* \ 1061 2>/dev/null 1062 rmdir "${DEST_DIR}${manbase}/cat${sec}" \ 1063 2>/dev/null 1064 fi 1065 done 1066 done 1067 return $failed 1068} 1069 1070 1071# 1072# ddbonpanic 1073# 1074 1075additem ddbonpanic "verify ddb.onpanic is configured in sysctl.conf" 1076do_ddbonpanic() 1077{ 1078 [ -n "$1" ] || err 3 "USAGE: do_ddbonpanic fix|check" 1079 1080 if ${GREP} -E '^#*[[:space:]]*ddb\.onpanic[[:space:]]*\??=[[:space:]]*[[:digit:]]+' \ 1081 "${DEST_DIR}/etc/sysctl.conf" >/dev/null 2>&1 1082 then 1083 result=0 1084 else 1085 if [ "$1" = check ]; then 1086 msg \ 1087 "The ddb.onpanic behaviour is not explicitly specified in /etc/sysctl.conf" 1088 result=1 1089 else 1090 echo >> "${DEST_DIR}/etc/sysctl.conf" 1091 ${SED} < "${SRC_DIR}/etc/sysctl.conf" \ 1092 -e '/^ddb\.onpanic/q' | \ 1093 ${SED} -e '1,/^$/d' >> \ 1094 "${DEST_DIR}/etc/sysctl.conf" 1095 result=$? 1096 fi 1097 fi 1098 return ${result} 1099} 1100 1101 1102# 1103# defaults 1104# 1105 1106additem defaults "/etc/defaults/ being up to date" 1107do_defaults() 1108{ 1109 [ -n "$1" ] || err 3 "USAGE: do_defaults fix|check" 1110 local op="$1" 1111 local failed=0 1112 local etcsets=$(getetcsets) 1113 1114 local rc_exclude_scripts="" 1115 if $SOURCEMODE; then 1116 # For most architectures rc.conf(5) should be the same as the 1117 # one obtained from a source directory, except for the ones 1118 # that have an append file for it. 1119 local rc_conf_app="${SRC_DIR}/etc/etc.${MACHINE}/rc.conf.append" 1120 if [ -f "${rc_conf_app}" ]; then 1121 rc_exclude_scripts="rc.conf" 1122 1123 # Generate and compare the correct rc.conf(5) file 1124 mkdir "${SCRATCHDIR}/defaults" 1125 1126 cat "${SRC_DIR}/etc/defaults/rc.conf" "${rc_conf_app}" \ 1127 > "${SCRATCHDIR}/defaults/rc.conf" 1128 1129 compare_dir "${op}" "${SCRATCHDIR}/defaults" \ 1130 "${DEST_DIR}/etc/defaults" \ 1131 444 \ 1132 "rc.conf" 1133 failed=$(( ${failed} + $? )) 1134 fi 1135 fi 1136 1137 find_file_in_dirlist pf.boot.conf "pf.boot.conf" \ 1138 "${SRC_DIR}/usr.sbin/pf/etc/defaults" "${SRC_DIR}/etc/defaults" \ 1139 || return 1 1140 # ${dir} is set by find_file_in_dirlist() 1141 compare_dir "$op" "${dir}" "${DEST_DIR}/etc/defaults" 444 pf.boot.conf 1142 failed=$(( ${failed} + $? )) 1143 1144 rc_exclude_scripts="${rc_exclude_scripts} pf.boot.conf" 1145 1146 local rc_default_conf_files="$(select_set_files /etc/defaults/ \ 1147 "/etc/defaults/\([^[:space:]]*\.conf\)" ${etcsets} | \ 1148 exclude ${rc_exclude_scripts})" 1149 compare_dir "$op" "${SRC_DIR}/etc/defaults" "${DEST_DIR}/etc/defaults" \ 1150 444 \ 1151 ${rc_default_conf_files} 1152 failed=$(( ${failed} + $? )) 1153 1154 1155 return ${failed} 1156} 1157 1158 1159# 1160# dhcpcd 1161# 1162 1163additem dhcpcd "dhcpcd configuration is up to date" 1164do_dhcpcd() 1165{ 1166 [ -n "$1" ] || err 3 "USAGE: do_dhcpcd fix|check" 1167 op="$1" 1168 failed=0 1169 1170 find_file_in_dirlist dhcpcd.conf "dhcpcd.conf" \ 1171 "${SRC_DIR}/external/bsd/dhcpcd/dist/src" \ 1172 "${SRC_DIR}/etc" || return 1 1173 # ${dir} is set by find_file_in_dirlist() 1174 populate_dir "$op" true "${dir}" "${DEST_DIR}/etc" 644 dhcpcd.conf 1175 failed=$(( ${failed} + $? )) 1176 1177 check_dir "${op}" "${DEST_DIR}/var/db/dhcpcd" 755 1178 failed=$(( ${failed} + $? )) 1179 1180 move_file "${op}" \ 1181 "${DEST_DIR}/etc/dhcpcd.duid" \ 1182 "${DEST_DIR}/var/db/dhcpcd/duid" 1183 failed=$(( ${failed} + $? )) 1184 1185 move_file "${op}" \ 1186 "${DEST_DIR}/etc/dhcpcd.secret" \ 1187 "${DEST_DIR}/var/db/dhcpcd/secret" 1188 failed=$(( ${failed} + $? )) 1189 1190 move_file "${op}" \ 1191 "${DEST_DIR}/var/db/dhcpcd-rdm.monotonic" \ 1192 "${DEST_DIR}/var/db/dhcpcd/rdm_monotonic" 1193 failed=$(( ${failed} + $? )) 1194 1195 for lease in "${DEST_DIR}/var/db/dhcpcd-"*.lease*; do 1196 [ -f "${lease}" ] || continue 1197 new_lease=$(basename "${lease}" | ${SED} -e 's/dhcpcd-//') 1198 new_lease="${DEST_DIR}/var/db/dhcpcd/${new_lease}" 1199 move_file "${op}" "${lease}" "${new_lease}" 1200 failed=$(( ${failed} + $? )) 1201 done 1202 1203 chroot_dir="${DEST_DIR}/var/chroot/dhcpcd" 1204 move_file "${op}" \ 1205 "${chroot_dir}/var/db/dhcpcd/duid" \ 1206 "${DEST_DIR}/var/db/dhcpcd/duid" 1207 failed=$(( ${failed} + $? )) 1208 1209 move_file "${op}" \ 1210 "${chroot_dir}/var/db/dhcpcd/secret" \ 1211 "${DEST_DIR}/var/db/dhcpcd/secret" 1212 failed=$(( ${failed} + $? )) 1213 1214 move_file "${op}" \ 1215 "${chroot_dir}/var/db/dhcpcd/rdm_monotonic" \ 1216 "${DEST_DIR}/var/db/dhcpcd/rdm_monotonic" 1217 failed=$(( ${failed} + $? )) 1218 1219 for lease in "${chroot_dir}/var/db/dhcpcd/"*.lease*; do 1220 [ -f "${lease}" ] || continue 1221 new_lease="${DEST_DIR}/var/db/dhcpcd/$(basename ${lease})" 1222 move_file "${op}" "${lease}" "${new_lease}" 1223 failed=$(( ${failed} + $? )) 1224 done 1225 1226 # Ensure chroot is now empty 1227 for dir in \ 1228 $(find ${chroot_dir} ! -type d) \ 1229 $(find ${chroot_dir} -type d -mindepth 1 | sort -r) 1230 do 1231 echo "/var/chroot/dhcpcd${dir##${chroot_dir}}" 1232 done | obsolete_paths "${op}" 1233 failed=$(( ${failed} + $? )) 1234 1235 contents_owner "${op}" "${DEST_DIR}/var/db/dhcpcd" root wheel 1236 failed=$(( ${failed} + $? )) 1237 1238 return ${failed} 1239} 1240 1241 1242# 1243# dhcpcdrundir 1244# 1245 1246additem dhcpcdrundir "accidentally created /@RUNDIR@ does not exist" 1247do_dhcpcdrundir() 1248{ 1249 [ -n "$1" ] || err 3 "USAGE: do_dhcpcdrundir fix|check" 1250 op="$1" 1251 failed=0 1252 1253 if [ -d "${DEST_DIR}/@RUNDIR@" ]; then 1254 if [ "${op}" = "check" ]; then 1255 msg "Remove erroneously created /@RUNDIR@" 1256 failed=1 1257 elif ! rm -r "${DEST_DIR}/@RUNDIR@"; then 1258 msg "Failed to remove ${DEST_DIR}/@RUNDIR@" 1259 failed=1 1260 else 1261 msg "Removed erroneously created ${DEST_DIR}/@RUNDIR@" 1262 fi 1263 fi 1264 return ${failed} 1265} 1266 1267 1268# 1269# envsys 1270# 1271 1272additem envsys "envsys configuration is up to date" 1273do_envsys() 1274{ 1275 [ -n "$1" ] || err 3 "USAGE: do_envsys fix|check" 1276 local op="$1" 1277 local failed=0 1278 local etcsets=$(getetcsets) 1279 1280 populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1281 envsys.conf 1282 failed=$(( ${failed} + $? )) 1283 1284 local powerd_scripts="$(select_set_files /etc/powerd/scripts/ \ 1285 "/etc/powerd/scripts/\([^[:space:]/]*\)" ${etcsets})" 1286 1287 populate_dir "$op" true "${SRC_DIR}/etc/powerd/scripts" \ 1288 "${DEST_DIR}/etc/powerd/scripts" \ 1289 555 \ 1290 ${powerd_scripts} 1291 failed=$(( ${failed} + $? )) 1292 1293 return ${failed} 1294} 1295 1296 1297# 1298# fontconfig 1299# 1300 1301additem fontconfig "X11 font configuration is up to date" 1302do_fontconfig() 1303{ 1304 [ -n "$1" ] || err 3 "USAGE: do_fontconfig fix|check" 1305 op="$1" 1306 failed=0 1307 1308 # First, check for updates we can handle. 1309 if ! $SOURCEMODE; then 1310 FONTCONFIG_DIR="${SRC_DIR}/etc/fonts/conf.avail" 1311 else 1312 FONTCONFIG_DIR="${XSRC_DIR}/external/mit/fontconfig/dist/conf.d" 1313 fi 1314 1315 if [ ! -d "${FONTCONFIG_DIR}" ]; then 1316 msg "${FONTCONFIG_DIR} is not a directory; skipping check" 1317 return 0 1318 fi 1319 local regular_fonts=" 132010-autohint.conf 132110-no-sub-pixel.conf 132210-scale-bitmap-fonts.conf 132310-sub-pixel-bgr.conf 132410-sub-pixel-rgb.conf 132510-sub-pixel-vbgr.conf 132610-sub-pixel-vrgb.conf 132710-unhinted.conf 132811-lcdfilter-default.conf 132911-lcdfilter-legacy.conf 133011-lcdfilter-light.conf 133120-unhint-small-vera.conf 133225-unhint-nonlatin.conf 133330-metric-aliases.conf 133440-nonlatin.conf 133545-generic.conf 133645-latin.conf 133749-sansserif.conf 133850-user.conf 133951-local.conf 134060-generic.conf 134160-latin.conf 134265-fonts-persian.conf 134365-khmer.conf 134465-nonlatin.conf 134569-unifont.conf 134670-no-bitmaps.conf 134770-yes-bitmaps.conf 134880-delicious.conf 134990-synthetic.conf 1350" 1351 populate_dir "$op" false "${FONTCONFIG_DIR}" \ 1352 "${DEST_DIR}/etc/fonts/conf.avail" \ 1353 444 \ 1354 ${regular_fonts} 1355 failed=$(( ${failed} + $? )) 1356 1357 if ! $SOURCEMODE; then 1358 FONTS_DIR="${SRC_DIR}/etc/fonts" 1359 else 1360 FONTS_DIR="${SRC_DIR}/external/mit/xorg/lib/fontconfig/etc" 1361 fi 1362 1363 populate_dir "$op" false "${FONTS_DIR}" "${DEST_DIR}/etc/fonts" 444 \ 1364 fonts.conf 1365 failed=$(( ${failed} + $? )) 1366 1367 # We can't modify conf.d easily; someone might have removed a file. 1368 1369 # Look for old files that need to be deleted. 1370 obsolete_fonts=" 137110-autohint.conf 137210-no-sub-pixel.conf 137310-sub-pixel-bgr.conf 137410-sub-pixel-rgb.conf 137510-sub-pixel-vbgr.conf 137610-sub-pixel-vrgb.conf 137710-unhinted.conf 137825-unhint-nonlatin.conf 137965-khmer.conf 138070-no-bitmaps.conf 138170-yes-bitmaps.conf 1382" 1383 failed_fonts="" 1384 for i in ${obsolete_fonts}; do 1385 if [ -f "${DEST_DIR}/etc/fonts/conf.d/$i" ]; then 1386 conf_d_failed=1 1387 failed_fonts="$failed_fonts $i" 1388 fi 1389 done 1390 1391 if [ -n "$failed_fonts" ]; then 1392 msg \ 1393 "Broken fontconfig configuration found; please delete these files:" 1394 msg "[$failed_fonts]" 1395 failed=$(( ${failed} + 1 )) 1396 fi 1397 1398 return ${failed} 1399} 1400 1401 1402# 1403# gid 1404# 1405 1406additem gid "required groups in /etc/group" 1407do_gid() 1408{ 1409 [ -n "$1" ] || err 3 "USAGE: do_gid fix|check" 1410 1411 check_ids "$1" groups "${DEST_DIR}/etc/group" \ 1412 "${SRC_DIR}/etc/group" 14 \ 1413 named ntpd sshd SKIP _pflogd _rwhod staff _proxy _timedc \ 1414 _sdpd _httpd _mdnsd _tests _tcpdump _tss _gpio _rtadvd SKIP \ 1415 _unbound _nsd nvmm _dhcpcd 1416} 1417 1418 1419# 1420# gpio 1421# 1422 1423additem gpio "gpio configuration is up to date" 1424do_gpio() 1425{ 1426 [ -n "$1" ] || err 3 "USAGE: do_gpio fix|check" 1427 op="$1" 1428 failed=0 1429 1430 populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1431 gpio.conf 1432 failed=$(( ${failed} + $? )) 1433 1434 return ${failed} 1435} 1436 1437 1438# 1439# hosts 1440# 1441 1442additem hosts "/etc/hosts being up to date" 1443do_hosts() 1444{ 1445 [ -n "$1" ] || err 3 "USAGE: do_hosts fix|check" 1446 1447 modify_file "$1" "${DEST_DIR}/etc/hosts" "${SCRATCHDIR}/hosts" ' 1448 /^(127\.0\.0\.1|::1)[ ]+[^\.]*$/ { 1449 print $0, "localhost." 1450 next 1451 } 1452 { print } 1453 ' 1454 return $? 1455} 1456 1457 1458# 1459# iscsi 1460# 1461 1462additem iscsi "/etc/iscsi is populated" 1463do_iscsi() 1464{ 1465 [ -n "$1" ] || err 3 "USAGE: do_iscsi fix|check" 1466 1467 populate_dir "${op}" true \ 1468 "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 600 auths 1469 populate_dir "${op}" true \ 1470 "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 644 targets 1471 return $? 1472} 1473 1474 1475# 1476# mailerconf 1477# 1478 1479adddisableditem mailerconf "update /etc/mailer.conf after sendmail removal" 1480do_mailerconf() 1481{ 1482 [ -n "$1" ] || err 3 "USAGE: do_mailterconf fix|check" 1483 op="$1" 1484 1485 failed=0 1486 mta_path="$(${AWK} '/^sendmail[ \t]/{print$2}' \ 1487 "${DEST_DIR}/etc/mailer.conf")" 1488 old_sendmail_path="/usr/libexec/sendmail/sendmail" 1489 if [ "${mta_path}" = "${old_sendmail_path}" ]; then 1490 if [ "$op" = check ]; then 1491 msg "mailer.conf points to obsolete ${old_sendmail_path}" 1492 failed=1; 1493 else 1494 populate_dir "${op}" false \ 1495 "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 mailer.conf 1496 failed=$? 1497 fi 1498 fi 1499 1500 return ${failed} 1501} 1502 1503 1504# 1505# makedev 1506# 1507 1508additem makedev "/dev/MAKEDEV being up to date" 1509do_makedev() 1510{ 1511 [ -n "$1" ] || err 3 "USAGE: do_makedev fix|check" 1512 failed=0 1513 1514 if [ -f "${SRC_DIR}/etc/MAKEDEV.tmpl" ]; then 1515 # generate MAKEDEV from source if source is available 1516 env MACHINE="${MACHINE}" \ 1517 MACHINE_ARCH="${MACHINE_ARCH}" \ 1518 NETBSDSRCDIR="${SRC_DIR}" \ 1519 ${AWK} -f "${SRC_DIR}/etc/MAKEDEV.awk" \ 1520 "${SRC_DIR}/etc/MAKEDEV.tmpl" > "${SCRATCHDIR}/MAKEDEV" 1521 fi 1522 1523 find_file_in_dirlist MAKEDEV "MAKEDEV" \ 1524 "${SCRATCHDIR}" "${SRC_DIR}/dev" \ 1525 || return 1 1526 # ${dir} is set by find_file_in_dirlist() 1527 find_makedev 1528 compare_dir "$1" "${dir}" "${MAKEDEV_DIR}" 555 MAKEDEV 1529 failed=$(( ${failed} + $? )) 1530 1531 find_file_in_dirlist MAKEDEV.local "MAKEDEV.local" \ 1532 "${SRC_DIR}/etc" "${SRC_DIR}/dev" \ 1533 || return 1 1534 # ${dir} is set by find_file_in_dirlist() 1535 compare_dir "$1" "${dir}" "${DEST_DIR}/dev" 555 MAKEDEV.local 1536 failed=$(( ${failed} + $? )) 1537 1538 return ${failed} 1539} 1540 1541 1542# 1543# man.conf 1544# 1545 1546additem manconf "check for a mandoc usage in /etc/man.conf" 1547do_manconf() 1548{ 1549 [ -n "$1" ] || err 3 "USAGE: do_manconf fix|check" 1550 op="$1" 1551 failed=0 1552 1553 [ -f "${DEST_DIR}/etc/man.conf" ] || return 0 1554 if ${GREP} -w "mandoc" "${DEST_DIR}/etc/man.conf" >/dev/null 2>&1; 1555 then 1556 failed=0; 1557 else 1558 failed=1 1559 notfixed="" 1560 if [ "${op}" = "fix" ]; then 1561 notfixed="${NOT_FIXED}" 1562 fi 1563 msg "The file /etc/man.conf has not been adapted to mandoc usage; you" 1564 msg "probably want to copy a new version over. ${notfixed}" 1565 fi 1566 1567 return ${failed} 1568} 1569 1570 1571# 1572# motd 1573# 1574 1575additem motd "contents of motd" 1576do_motd() 1577{ 1578 [ -n "$1" ] || err 3 "USAGE: do_motd fix|check" 1579 1580 if ${GREP} -i 'http://www.NetBSD.org/Misc/send-pr.html' \ 1581 "${DEST_DIR}/etc/motd" >/dev/null 2>&1 \ 1582 || ${GREP} -i 'https*://www.NetBSD.org/support/send-pr.html' \ 1583 "${DEST_DIR}/etc/motd" >/dev/null 2>&1 1584 then 1585 tmp1="$(mktemp /tmp/postinstall.motd.XXXXXXXX)" 1586 tmp2="$(mktemp /tmp/postinstall.motd.XXXXXXXX)" 1587 ${SED} '1,2d' <"${SRC_DIR}/etc/motd" >"${tmp1}" 1588 ${SED} '1,2d' <"${DEST_DIR}/etc/motd" >"${tmp2}" 1589 1590 if [ "$1" = check ]; then 1591 cmp -s "${tmp1}" "${tmp2}" 1592 result=$? 1593 if [ "${result}" -ne 0 ]; then 1594 msg \ 1595 "Bug reporting messages do not seem to match the installed release" 1596 fi 1597 else 1598 head -n 2 "${DEST_DIR}/etc/motd" >"${tmp1}" 1599 ${SED} '1,2d' <"${SRC_DIR}/etc/motd" >>"${tmp1}" 1600 cp "${tmp1}" "${DEST_DIR}/etc/motd" 1601 result=0 1602 fi 1603 1604 rm -f "${tmp1}" "${tmp2}" 1605 else 1606 result=0 1607 fi 1608 1609 return ${result} 1610} 1611 1612 1613# 1614# mtree 1615# 1616 1617additem mtree "/etc/mtree/ being up to date" 1618do_mtree() 1619{ 1620 [ -n "$1" ] || err 3 "USAGE: do_mtree fix|check" 1621 failed=0 1622 1623 compare_dir "$1" "${SRC_DIR}/etc/mtree" "${DEST_DIR}/etc/mtree" 444 special 1624 failed=$(( ${failed} + $? )) 1625 1626 if ! $SOURCEMODE; then 1627 MTREE_DIR="${SRC_DIR}/etc/mtree" 1628 else 1629 /bin/rm -rf "${SCRATCHDIR}/obj" 1630 mkdir "${SCRATCHDIR}/obj" 1631 ${MAKE} -s -C "${SRC_DIR}/etc/mtree" TOOL_AWK="${AWK}" \ 1632 MAKEOBJDIR="${SCRATCHDIR}/obj" emit_dist_file > \ 1633 "${SCRATCHDIR}/NetBSD.dist" 1634 MTREE_DIR="${SCRATCHDIR}" 1635 /bin/rm -rf "${SCRATCHDIR}/obj" 1636 fi 1637 compare_dir "$1" "${MTREE_DIR}" "${DEST_DIR}/etc/mtree" 444 NetBSD.dist 1638 failed=$(( ${failed} + $? )) 1639 1640 return ${failed} 1641} 1642 1643 1644# 1645# named 1646# 1647 1648additem named "named configuration update" 1649do_named() 1650{ 1651 [ -n "$1" ] || err 3 "USAGE: do_named fix|check" 1652 op="$1" 1653 1654 move_file "${op}" \ 1655 "${DEST_DIR}/etc/namedb/named.conf" \ 1656 "${DEST_DIR}/etc/named.conf" 1657 1658 compare_dir "${op}" "${SRC_DIR}/etc/namedb" "${DEST_DIR}/etc/namedb" \ 1659 644 \ 1660 root.cache 1661} 1662 1663 1664# 1665# pam 1666# 1667 1668additem pam "/etc/pam.d is populated" 1669do_pam() 1670{ 1671 [ -n "$1" ] || err 3 "USAGE: do_pam fix|check" 1672 op="$1" 1673 failed=0 1674 1675 populate_dir "${op}" true "${SRC_DIR}/etc/pam.d" \ 1676 "${DEST_DIR}/etc/pam.d" 644 \ 1677 README cron display_manager ftpd gdm imap kde login other \ 1678 passwd pop3 ppp racoon rexecd rsh sshd su system telnetd \ 1679 xdm xserver 1680 1681 failed=$(( ${failed} + $? )) 1682 1683 return ${failed} 1684} 1685 1686 1687# 1688# periodic 1689# 1690 1691additem periodic "/etc/{daily,weekly,monthly,security} being up to date" 1692do_periodic() 1693{ 1694 [ -n "$1" ] || err 3 "USAGE: do_periodic fix|check" 1695 1696 compare_dir "$1" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1697 daily weekly monthly security 1698} 1699 1700 1701# 1702# pf 1703# 1704 1705additem pf "pf configuration being up to date" 1706do_pf() 1707{ 1708 [ -n "$1" ] || err 3 "USAGE: do_pf fix|check" 1709 op="$1" 1710 failed=0 1711 1712 find_file_in_dirlist pf.os "pf.os" \ 1713 "${SRC_DIR}/dist/pf/etc" "${SRC_DIR}/etc" \ 1714 || return 1 1715 # ${dir} is set by find_file_in_dirlist() 1716 populate_dir "${op}" true \ 1717 "${dir}" "${DEST_DIR}/etc" 644 \ 1718 pf.conf 1719 failed=$(( ${failed} + $? )) 1720 1721 compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 pf.os 1722 failed=$(( ${failed} + $? )) 1723 1724 return ${failed} 1725} 1726 1727 1728# 1729# ptyfsoldnodes 1730# 1731 1732additem ptyfsoldnodes "remove legacy device nodes when using ptyfs" 1733do_ptyfsoldnodes() 1734{ 1735 [ -n "$1" ] || err 3 "USAGE: do_ptyfsoldnodes fix|check" 1736 _ptyfs_op="$1" 1737 1738 # Check whether ptyfs is in use 1739 failed=0; 1740 if ! ${GREP} -E "^ptyfs" "${DEST_DIR}/etc/fstab" > /dev/null; then 1741 msg "ptyfs is not in use" 1742 return 0 1743 fi 1744 1745 if [ ! -e "${DEST_DIR}/dev/pts" ]; then 1746 msg "ptyfs is not properly configured: missing /dev/pts" 1747 return 1 1748 fi 1749 1750 # Find the device major numbers for the pty master and slave 1751 # devices, by parsing the output from "MAKEDEV -s pty0". 1752 # 1753 # Output from MAKEDEV looks like this: 1754 # ./ttyp0 type=char device=netbsd,5,0 mode=666 gid=0 uid=0 1755 # ./ptyp0 type=char device=netbsd,6,0 mode=666 gid=0 uid=0 1756 # 1757 # Output from awk, used in the eval statement, looks like this: 1758 # maj_ptym=6; maj_ptys=5; 1759 # 1760 find_makedev 1761 eval "$( 1762 ${HOST_SH} "${MAKEDEV_DIR}/MAKEDEV" -s pty0 2>/dev/null \ 1763 | ${AWK} '\ 1764 BEGIN { before_re = ".*device=[a-zA-Z]*,"; after_re = ",.*"; } 1765 /ptyp0/ { maj_ptym = gensub(before_re, "", 1, $0); 1766 maj_ptym = gensub(after_re, "", 1, maj_ptym); } 1767 /ttyp0/ { maj_ptys = gensub(before_re, "", 1, $0); 1768 maj_ptys = gensub(after_re, "", 1, maj_ptys); } 1769 END { print "maj_ptym=" maj_ptym "; maj_ptys=" maj_ptys ";"; } 1770 ' 1771 )" 1772 #msg "Major numbers are maj_ptym=${maj_ptym} maj_ptys=${maj_ptys}" 1773 if [ -z "$maj_ptym" ] || [ -z "$maj_ptys" ]; then 1774 msg "Cannot find device major numbers for pty master and slave" 1775 return 1 1776 fi 1777 1778 # look for /dev/[pt]ty[p-zP-T][0-9a-zA-Z], and check that they 1779 # have the expected device major numbers. ttyv* is typically not a 1780 # pty device, but we check it anyway. 1781 # 1782 # The "for d1" loop is intended to avoid overflowing ARG_MAX; 1783 # otherwise we could have used a single glob pattern. 1784 # 1785 # If there are no files that match a particular pattern, 1786 # then stat prints something like: 1787 # stat: /dev/[pt]tyx?: lstat: No such file or directory 1788 # and we ignore it. XXX: We also ignore other error messages. 1789 # 1790 _ptyfs_tmp="$(mktemp /tmp/postinstall.ptyfs.XXXXXXXX)" 1791 for d1 in p q r s t u v w x y z P Q R S T; do 1792 ${STAT} -f "%Hr %N" "${DEST_DIR}/dev/"[pt]ty${d1}? 2>&1 1793 done \ 1794 | while read -r major node ; do 1795 case "$major" in 1796 ${maj_ptym}|${maj_ptys}) echo "$node" ;; 1797 esac 1798 done >"${_ptyfs_tmp}" 1799 1800 _desc="legacy device node" 1801 while read node; do 1802 if [ "${_ptyfs_op}" = "check" ]; then 1803 msg "Remove ${_desc} ${node}" 1804 failed=1 1805 else # "fix" 1806 if rm "${node}"; then 1807 msg "Removed ${_desc} ${node}" 1808 else 1809 warn "Failed to remove ${_desc} ${node}" 1810 failed=1 1811 fi 1812 fi 1813 done < "${_ptyfs_tmp}" 1814 rm "${_ptyfs_tmp}" 1815 1816 return ${failed} 1817} 1818 1819 1820# 1821# pwd_mkdb 1822# 1823 1824additem pwd_mkdb "passwd database version" 1825do_pwd_mkdb() 1826{ 1827 [ -n "$1" ] || err 3 "USAGE: do_pwd_mkdb fix|check" 1828 op="$1" 1829 failed=0 1830 1831 # XXX Ideally, we should figure out the endianness of the 1832 # target machine, and add "-E B"/"-E L" to the db(1) flags, 1833 # and "-B"/"-L" to the pwd_mkdb(8) flags if the target is not 1834 # the same as the host machine. It probably doesn't matter, 1835 # because we don't expect "postinstall fix pwd_mkdb" to be 1836 # invoked during a cross build. 1837 1838 set -- $(${DB} -q -Sb -Ub -To -N hash "${DEST_DIR}/etc/pwd.db" \ 1839 'VERSION\0') 1840 case "$2" in 1841 '\001\000\000\000') return 0 ;; # version 1, little-endian 1842 '\000\000\000\001') return 0 ;; # version 1, big-endian 1843 esac 1844 1845 if [ "${op}" = "check" ]; then 1846 msg "Update format of passwd database" 1847 failed=1 1848 elif ! ${PWD_MKDB} -V 1 -d "${DEST_DIR:-/}" \ 1849 "${DEST_DIR}/etc/master.passwd"; 1850 then 1851 msg "Can't update format of passwd database" 1852 failed=1 1853 else 1854 msg "Updated format of passwd database" 1855 fi 1856 1857 return ${failed} 1858} 1859 1860 1861# 1862# rc 1863# 1864 1865# There is no info in src/distrib or /etc/mtree which rc* files 1866# can be overwritten unconditionally on upgrade. See PR/54741. 1867rc_644_files=" 1868rc 1869rc.subr 1870rc.shutdown 1871" 1872 1873rc_obsolete_vars=" 1874amd amd_master 1875btcontrol btcontrol_devices 1876critical_filesystems critical_filesystems_beforenet 1877mountcritlocal mountcritremote 1878network ip6forwarding 1879network nfsiod_flags 1880sdpd sdpd_control 1881sdpd sdpd_groupname 1882sdpd sdpd_username 1883sysctl defcorename 1884" 1885 1886update_rc() 1887{ 1888 local op=$1 1889 local dir=$2 1890 local name=$3 1891 local bindir=$4 1892 local rcdir=$5 1893 1894 if [ ! -x "${DEST_DIR}/${bindir}/${name}" ]; then 1895 return 0 1896 fi 1897 1898 if ! find_file_in_dirlist "${name}" "${name}" \ 1899 "${rcdir}" "${SRC_DIR}/etc/rc.d"; then 1900 return 1 1901 fi 1902 populate_dir "${op}" false "${dir}" "${DEST_DIR}/etc/rc.d" 555 "${name}" 1903 return $? 1904} 1905 1906# select non-obsolete files in a sets file 1907# $1: directory pattern 1908# $2: file pattern 1909# $3: filename 1910select_set_files() 1911{ 1912 local qdir="$(echo $1 | ${SED} -e s@/@\\\\/@g -e s/\\./\\\\./g)" 1913 ${SED} -n -e /obsolete/d \ 1914 -e "/^\.${qdir}/s@^.$2[[:space:]].*@\1@p" $3 1915} 1916 1917# select obsolete files in a sets file 1918# $1: directory pattern 1919# $2: file pattern 1920# $3: setname 1921select_obsolete_files() 1922{ 1923 if $SOURCEMODE; then 1924 ${SED} -n -e "/obsolete/s@\.$1$2[[:space:]].*@\1@p" \ 1925 "${SRC_DIR}/distrib/sets/lists/$3/mi" 1926 return 1927 fi 1928 1929 # On upgrade builds we don't extract the "etc" set so we 1930 # try to use the source set instead. See PR/54730 for 1931 # ways to better handle this. 1932 1933 local obsolete_dir 1934 1935 if [ $3 = "etc" ] ;then 1936 obsolete_dir="${SRC_DIR}/var/db/obsolete" 1937 else 1938 obsolete_dir="${DEST_DIR}/var/db/obsolete" 1939 fi 1940 ${SED} -n -e "s@\.$1$2\$@\1@p" "${obsolete_dir}/$3" 1941} 1942 1943getetcsets() 1944{ 1945 if $SOURCEMODE; then 1946 echo "${SRC_DIR}/distrib/sets/lists/etc/mi" 1947 else 1948 echo "${SRC_DIR}/etc/mtree/set.etc" 1949 fi 1950} 1951 1952additem rc "/etc/rc* and /etc/rc.d/ being up to date" 1953do_rc() 1954{ 1955 [ -n "$1" ] || err 3 "USAGE: do_rc fix|check" 1956 local op="$1" 1957 local failed=0 1958 local generated_scripts="" 1959 local etcsets=$(getetcsets) 1960 if [ "${MKX11}" != "no" ]; then 1961 generated_scripts="${generated_scripts} xdm xfs" 1962 fi 1963 1964 # Directories of external programs that have rc files (in bsd) 1965 local rc_external_files="blocklist nsd unbound" 1966 1967 # rc* files in /etc/ 1968 # XXX: at least rc.conf and rc.local shouldn't be updated. PR/54741 1969 #local rc_644_files="$(select_set_files /etc/rc \ 1970 # "/etc/\(rc[^[:space:]/]*\)" ${etcsets})" 1971 1972 # no-obsolete rc files in /etc/rc.d 1973 local rc_555_files="$(select_set_files /etc/rc.d/ \ 1974 "/etc/rc\.d/\([^[:space:]]*\)" ${etcsets} | \ 1975 exclude ${rc_external_files})" 1976 1977 # obsolete rc file in /etc/rc.d 1978 local rc_obsolete_files="$(select_obsolete_files /etc/rc.d/ \ 1979 "\([^[:space:]]*\)" etc)" 1980 1981 compare_dir "${op}" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \ 1982 ${rc_644_files} 1983 failed=$(( ${failed} + $? )) 1984 1985 local extra_scripts 1986 if ! $SOURCEMODE; then 1987 extra_scripts="${generated_scripts}" 1988 else 1989 extra_scripts="" 1990 fi 1991 1992 compare_dir "${op}" "${SRC_DIR}/etc/rc.d" "${DEST_DIR}/etc/rc.d" 555 \ 1993 ${rc_555_files} \ 1994 ${extra_scripts} 1995 failed=$(( ${failed} + $? )) 1996 1997 for i in ${rc_external_files}; do 1998 local rc_file 1999 case $i in 2000 *d) rc_file=${i};; 2001 *) rc_file=${i}d;; 2002 esac 2003 2004 update_rc "${op}" "${dir}" ${rc_file} /sbin \ 2005 "${SRC_DIR}/external/bsd/$i/etc/rc.d" 2006 failed=$(( ${failed} + $? )) 2007 done 2008 2009 if $SOURCEMODE && [ -n "${generated_scripts}" ]; then 2010 # generate scripts 2011 mkdir "${SCRATCHDIR}/rc" 2012 for f in ${generated_scripts}; do 2013 ${SED} -e "s,@X11ROOTDIR@,${X11ROOTDIR},g" \ 2014 < "${SRC_DIR}/etc/rc.d/${f}.in" \ 2015 > "${SCRATCHDIR}/rc/${f}" 2016 done 2017 compare_dir "${op}" "${SCRATCHDIR}/rc" \ 2018 "${DEST_DIR}/etc/rc.d" 555 \ 2019 ${generated_scripts} 2020 failed=$(( ${failed} + $? )) 2021 fi 2022 2023 # check for obsolete rc.d files 2024 for f in ${rc_obsolete_files}; do 2025 local fd="/etc/rc.d/${f}" 2026 [ -e "${DEST_DIR}${fd}" ] && echo "${fd}" 2027 done | obsolete_paths "${op}" 2028 failed=$(( ${failed} + $? )) 2029 2030 # check for obsolete rc.conf(5) variables 2031 set -- ${rc_obsolete_vars} 2032 while [ $# -gt 1 ]; do 2033 if rcconf_is_set "${op}" "$1" "$2" 1; then 2034 failed=1 2035 fi 2036 shift 2 2037 done 2038 2039 return ${failed} 2040} 2041 2042 2043# 2044# sendmail 2045# 2046 2047adddisableditem sendmail "remove obsolete sendmail configuration files and scripts" 2048do_sendmail() 2049{ 2050 [ -n "$1" ] || err 3 "USAGE: do_sendmail fix|check" 2051 op="$1" 2052 failed=0 2053 2054 # Don't complain if the "sendmail" package is installed because the 2055 # files might still be in use. 2056 if /usr/sbin/pkg_info -qe sendmail >/dev/null 2>&1; then 2057 return 0 2058 fi 2059 2060 for f in /etc/mail/helpfile /etc/mail/local-host-names \ 2061 /etc/mail/sendmail.cf /etc/mail/submit.cf /etc/rc.d/sendmail \ 2062 /etc/rc.d/smmsp /usr/share/misc/sendmail.hf \ 2063 $( ( find "${DEST_DIR}/usr/share/sendmail" -type f ; \ 2064 find "${DEST_DIR}/usr/share/sendmail" -type d \ 2065 ) | unprefix "${DEST_DIR}" ) \ 2066 /var/log/sendmail.st \ 2067 /var/spool/clientmqueue \ 2068 /var/spool/mqueue 2069 do 2070 [ -e "${DEST_DIR}${f}" ] && echo "${f}" 2071 done | obsolete_paths "${op}" 2072 failed=$(( ${failed} + $? )) 2073 2074 return ${failed} 2075} 2076 2077 2078# 2079# ssh 2080# 2081 2082additem ssh "ssh configuration update" 2083do_ssh() 2084{ 2085 [ -n "$1" ] || err 3 "USAGE: do_ssh fix|check" 2086 op="$1" 2087 2088 failed=0 2089 _etcssh="${DEST_DIR}/etc/ssh" 2090 if ! check_dir "${op}" "${_etcssh}" 755; then 2091 failed=1 2092 fi 2093 2094 if [ ${failed} -eq 0 ]; then 2095 for f in \ 2096 ssh_known_hosts ssh_known_hosts2 \ 2097 ssh_host_dsa_key ssh_host_dsa_key.pub \ 2098 ssh_host_rsa_key ssh_host_rsa_key.pub \ 2099 ssh_host_key ssh_host_key.pub \ 2100 ; do 2101 if ! move_file "${op}" \ 2102 "${DEST_DIR}/etc/${f}" "${_etcssh}/${f}" ; then 2103 failed=1 2104 fi 2105 done 2106 for f in sshd.conf ssh.conf ; do 2107 # /etc/ssh/ssh{,d}.conf -> ssh{,d}_config 2108 # 2109 if ! move_file "${op}" \ 2110 "${_etcssh}/${f}" "${_etcssh}/${f%.conf}_config" ; 2111 then 2112 failed=1 2113 fi 2114 # /etc/ssh{,d}.conf -> /etc/ssh/ssh{,d}_config 2115 # 2116 if ! move_file "${op}" \ 2117 "${DEST_DIR}/etc/${f}" \ 2118 "${_etcssh}/${f%.conf}_config" ; 2119 then 2120 failed=1 2121 fi 2122 done 2123 fi 2124 2125 sshdconf="" 2126 for f in \ 2127 "${_etcssh}/sshd_config" \ 2128 "${_etcssh}/sshd.conf" \ 2129 "${DEST_DIR}/etc/sshd.conf" ; do 2130 if [ -f "${f}" ]; then 2131 sshdconf="${f}" 2132 break 2133 fi 2134 done 2135 if [ -n "${sshdconf}" ]; then 2136 modify_file "${op}" "${sshdconf}" "${SCRATCHDIR}/sshdconf" ' 2137 /^[^#$]/ { 2138 kw = tolower($1) 2139 if (kw == "hostkey" && 2140 $2 ~ /^\/etc\/+ssh_host(_[dr]sa)?_key$/ ) { 2141 sub(/\/etc\/+/, "/etc/ssh/") 2142 } 2143 if (kw == "rhostsauthentication" || 2144 kw == "verifyreversemapping" || 2145 kw == "reversemappingcheck") { 2146 sub(/^/, "# DEPRECATED:\t") 2147 } 2148 } 2149 { print } 2150 ' 2151 failed=$(( ${failed} + $? )) 2152 fi 2153 2154 if ! find_file_in_dirlist moduli "moduli" \ 2155 "${SRC_DIR}/crypto/external/bsd/openssh/dist" "${SRC_DIR}/etc" ; then 2156 failed=1 2157 # ${dir} is set by find_file_in_dirlist() 2158 elif ! compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 moduli; then 2159 failed=1 2160 fi 2161 2162 if ! check_dir "${op}" "${DEST_DIR}/var/chroot/sshd" 755 ; then 2163 failed=1 2164 fi 2165 2166 if rcconf_is_set "${op}" sshd sshd_conf_dir 1; then 2167 failed=1 2168 fi 2169 2170 return ${failed} 2171} 2172 2173 2174# 2175# tcpdumpchroot 2176# 2177 2178additem tcpdumpchroot "remove /var/chroot/tcpdump/etc/protocols" 2179do_tcpdumpchroot() 2180{ 2181 [ -n "$1" ] || err 3 "USAGE: do_tcpdumpchroot fix|check" 2182 2183 failed=0; 2184 if [ -r "${DEST_DIR}/var/chroot/tcpdump/etc/protocols" ]; then 2185 if [ "$1" = "fix" ]; then 2186 rm "${DEST_DIR}/var/chroot/tcpdump/etc/protocols" 2187 failed=$(( ${failed} + $? )) 2188 rmdir "${DEST_DIR}/var/chroot/tcpdump/etc" 2189 failed=$(( ${failed} + $? )) 2190 else 2191 failed=1 2192 fi 2193 fi 2194 return ${failed} 2195} 2196 2197 2198# 2199# uid 2200# 2201 2202additem uid "required users in /etc/master.passwd" 2203do_uid() 2204{ 2205 [ -n "$1" ] || err 3 "USAGE: do_uid fix|check" 2206 2207 check_ids "$1" users "${DEST_DIR}/etc/master.passwd" \ 2208 "${SRC_DIR}/etc/master.passwd" 12 \ 2209 postfix SKIP named ntpd sshd SKIP _pflogd _rwhod SKIP _proxy \ 2210 _timedc _sdpd _httpd _mdnsd _tests _tcpdump _tss SKIP _rtadvd \ 2211 SKIP _unbound _nsd SKIP _dhcpcd 2212} 2213 2214 2215# 2216# varrwho 2217# 2218 2219additem varrwho "required ownership of files in /var/rwho" 2220do_varrwho() 2221{ 2222 [ -n "$1" ] || err 3 "USAGE: do_varrwho fix|check" 2223 2224 contents_owner "$1" "${DEST_DIR}/var/rwho" _rwhod _rwhod 2225} 2226 2227 2228# 2229# varshm 2230# 2231 2232additem varshm "check for a tmpfs mounted on /var/shm" 2233do_varshm() 2234{ 2235 [ -n "$1" ] || err 3 "USAGE: do_varshm fix|check" 2236 op="$1" 2237 failed=0 2238 2239 [ -f "${DEST_DIR}/etc/fstab" ] || return 0 2240 if ${GREP} -E "^var_shm_symlink" "${DEST_DIR}/etc/rc.conf" >/dev/null 2>&1; 2241 then 2242 failed=0; 2243 elif ${GREP} -w "/var/shm" "${DEST_DIR}/etc/fstab" >/dev/null 2>&1; 2244 then 2245 failed=0; 2246 else 2247 if [ "${op}" = "check" ]; then 2248 failed=1 2249 msg "No /var/shm mount found in ${DEST_DIR}/etc/fstab" 2250 elif [ "${op}" = "fix" ]; then 2251 printf '\ntmpfs\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n' \ 2252 >> "${DEST_DIR}/etc/fstab" 2253 msg "Added tmpfs with 25% ram limit as /var/shm" 2254 2255 fi 2256 fi 2257 2258 return ${failed} 2259} 2260 2261 2262# 2263# wscons 2264# 2265 2266additem wscons "wscons configuration file update" 2267do_wscons() 2268{ 2269 [ -n "$1" ] || err 3 "USAGE: do_wscons fix|check" 2270 op="$1" 2271 2272 [ -f "${DEST_DIR}/etc/wscons.conf" ] || return 0 2273 2274 failed=0 2275 notfixed="" 2276 if [ "${op}" = "fix" ]; then 2277 notfixed="${NOT_FIXED}" 2278 fi 2279 while read _type _arg1 _rest; do 2280 if [ "${_type}" = "mux" -a "${_arg1}" = "1" ]; then 2281 msg \ 2282 "Obsolete wscons.conf(5) entry \""${_type} ${_arg1}"\" found.${notfixed}" 2283 failed=1 2284 fi 2285 done < "${DEST_DIR}/etc/wscons.conf" 2286 2287 return ${failed} 2288} 2289 2290 2291# 2292# x11 2293# 2294 2295additem x11 "x11 configuration update" 2296do_x11() 2297{ 2298 [ -n "$1" ] || err 3 "USAGE: do_x11 fix|check" 2299 op="$1" 2300 2301 failed=0 2302 _etcx11="${DEST_DIR}/etc/X11" 2303 _libx11="" 2304 if [ ! -d "${_etcx11}" ]; then 2305 msg "${_etcx11} is not a directory; skipping check" 2306 return 0 2307 fi 2308 if [ -d "${DEST_DIR}/usr/X11R6/." ] 2309 then 2310 _libx11="${DEST_DIR}/usr/X11R6/lib/X11" 2311 if [ ! -d "${_libx11}" ]; then 2312 msg "${_libx11} is not a directory; skipping check" 2313 return 0 2314 fi 2315 fi 2316 2317 _notfixed="" 2318 if [ "${op}" = "fix" ]; then 2319 _notfixed="${NOT_FIXED}" 2320 fi 2321 2322 # check if /usr/X11R6/lib/X11 needs to migrate to /etc/X11 2323 if [ -n "${_libx11}" ]; then 2324 for d in \ 2325 fs lbxproxy proxymngr rstart twm xdm xinit xserver xsm \ 2326 ; do 2327 sd="${_libx11}/${d}" 2328 ld="/etc/X11/${d}" 2329 td="${DEST_DIR}${ld}" 2330 if [ -h "${sd}" ]; then 2331 continue 2332 elif [ -d "${sd}" ]; then 2333 tdfiles="$(find "${td}" \! -type d)" 2334 if [ -n "${tdfiles}" ]; then 2335 msg "${sd} exists yet ${td} already" \ 2336 "contains files${_notfixed}" 2337 else 2338 msg "Migrate ${sd} to ${td}${_notfixed}" 2339 fi 2340 failed=1 2341 elif [ -e "${sd}" ]; then 2342 msg "Unexpected file ${sd}${_notfixed}" 2343 continue 2344 else 2345 continue 2346 fi 2347 done 2348 fi 2349 2350 # check if xdm resources have been updated 2351 if [ -r ${_etcx11}/xdm/Xresources ] && \ 2352 ! ${GREP} 'inpColor:' ${_etcx11}/xdm/Xresources > /dev/null; then 2353 msg "Update ${_etcx11}/xdm/Xresources${_notfixed}" 2354 failed=1 2355 fi 2356 2357 return ${failed} 2358} 2359 2360 2361# 2362# xkb 2363# 2364# /usr/X11R7/lib/X11/xkb/symbols/pc used to be a directory, but changed 2365# to a file on 2009-06-12. Fixing this requires removing the directory 2366# (which we can do) and re-extracting the xbase set (which we can't do), 2367# or at least adding that one file (which we may be able to do if X11SRCDIR 2368# is available). 2369# 2370 2371additem xkb "clean up for xkbdata to xkeyboard-config upgrade" 2372do_xkb() 2373{ 2374 [ -n "$1" ] || err 3 "USAGE: do_xkb fix|check" 2375 op="$1" 2376 failed=0 2377 2378 pcpath="/usr/X11R7/lib/X11/xkb/symbols/pc" 2379 pcsrcdir="${X11SRCDIR}/external/mit/xkeyboard-config/dist/symbols" 2380 2381 filemsg="\ 2382${pcpath} was a directory, should be a file. 2383 To fix, extract the xbase set again." 2384 2385 _notfixed="" 2386 if [ "${op}" = "fix" ]; then 2387 _notfixed="${NOT_FIXED}" 2388 fi 2389 2390 if [ ! -d "${DEST_DIR}${pcpath}" ]; then 2391 return 0 2392 fi 2393 2394 # Delete obsolete files in the directory, and the directory 2395 # itself. If the directory contains unexpected extra files 2396 # then it will not be deleted. 2397 ( [ -f "${DEST_DIR}"/var/db/obsolete/xbase ] \ 2398 && ${SORT} -ru "${DEST_DIR}"/var/db/obsolete/xbase \ 2399 | ${GREP} -E "^\\.?${pcpath}/" ; 2400 echo "${pcpath}" ) \ 2401 | obsolete_paths "${op}" 2402 failed=$(( ${failed} + $? )) 2403 2404 # If the directory was removed above, then try to replace it with 2405 # a file. 2406 if [ -d "${DEST_DIR}${pcpath}" ]; then 2407 msg "${filemsg}${_notfixed}" 2408 failed=$(( ${failed} + 1 )) 2409 else 2410 if ! find_file_in_dirlist pc "${pcpath}" \ 2411 "${pcsrcdir}" "${SRC_DIR}${pcpath%/*}" 2412 then 2413 msg "${filemsg}${_notfixed}" 2414 failed=$(( ${failed} + 1 )) 2415 else 2416 # ${dir} is set by find_file_in_dirlist() 2417 populate_dir "${op}" true \ 2418 "${dir}" "${DEST_DIR}${pcpath%/*}" 444 \ 2419 pc 2420 failed=$(( ${failed} + $? )) 2421 fi 2422 fi 2423 2424 return $failed 2425} 2426 2427 2428# 2429# obsolete_stand 2430# obsolete_stand_debug 2431# 2432 2433obsolete_stand_internal() 2434{ 2435 local prefix="$1" 2436 shift 2437 [ -n "$1" ] || err 3 "USAGE: do_obsolete_stand fix|check" 2438 local op="$1" 2439 local failed=0 2440 2441 for dir in \ 2442 ${prefix}/stand/${MACHINE} \ 2443 ${prefix}/stand/${MACHINE}-4xx \ 2444 ${prefix}/stand/${MACHINE}-booke \ 2445 ${prefix}/stand/${MACHINE}-xen \ 2446 ${prefix}/stand/${MACHINE}pae-xen 2447 do 2448 [ -d "${DEST_DIR}${dir}" ] && obsolete_stand "${dir}" 2449 done | obsolete_paths "${op}" 2450 failed=$(( ${failed} + $? )) 2451 2452 return ${failed} 2453} 2454 2455adddisableditem obsolete_stand "remove obsolete files from /stand" 2456do_obsolete_stand() 2457{ 2458 obsolete_stand_internal "" "$@" 2459 return $? 2460} 2461 2462adddisableditem obsolete_stand_debug "remove obsolete files from /usr/libdata/debug/stand" 2463do_obsolete_stand_debug() 2464{ 2465 obsolete_stand_internal "/usr/libdata/debug" "$@" 2466 return $? 2467} 2468 2469 2470# 2471# obsolete 2472# 2473# NOTE: This item is last to allow other items to move obsolete files. 2474# 2475 2476listarchsubdirs() 2477{ 2478 if ! $SOURCEMODE; then 2479 echo "@ARCHSUBDIRS@" 2480 else 2481 ${SED} -n -e '/ARCHDIR_SUBDIR/s/[[:space:]]//gp' \ 2482 "${SRC_DIR}/compat/archdirs.mk" 2483 fi 2484} 2485 2486getarchsubdirs() 2487{ 2488 local m 2489 case ${MACHINE_ARCH} in 2490 *arm*|*aarch64*) m=arm;; 2491 x86_64) m=amd64;; 2492 *) m=${MACHINE_ARCH};; 2493 esac 2494 2495 for i in $(listarchsubdirs); do 2496 echo $i 2497 done | ${SORT} -u | ${SED} -n -e "/=${m}/s@.*=${m}/\(.*\)@\1@p" 2498} 2499 2500getcompatlibdirs() 2501{ 2502 for i in $(getarchsubdirs); do 2503 if [ -d "${DEST_DIR}/usr/lib/$i" ]; then 2504 echo /usr/lib/$i 2505 fi 2506 done 2507} 2508 2509additem obsolete "remove obsolete file sets and minor libraries" 2510do_obsolete() 2511{ 2512 [ -n "$1" ] || err 3 "USAGE: do_obsolete fix|check" 2513 op="$1" 2514 failed=0 2515 2516 ${SORT} -ru "${DEST_DIR}"/var/db/obsolete/* | obsolete_paths "${op}" 2517 failed=$(( ${failed} + $? )) 2518 2519 ( 2520 obsolete_libs /lib 2521 obsolete_libs /usr/lib 2522 obsolete_libs /usr/lib/i18n 2523 obsolete_libs /usr/X11R6/lib 2524 obsolete_libs /usr/X11R7/lib 2525 for i in $(getcompatlibdirs); do 2526 obsolete_libs $i 2527 done 2528 ) | obsolete_paths "${op}" 2529 failed=$(( ${failed} + $? )) 2530 2531 return ${failed} 2532} 2533 2534 2535# 2536# end of items 2537# ------------ 2538# 2539 2540 2541help() 2542{ 2543 cat << _USAGE_ 2544Usage: ${PROGNAME} [-a ARCH] [-d DEST_DIR] [-m MACHINE] [-s SRC_ARG] [-x XSRC_DIR] OPERATION ... 2545 ${PROGNAME} -? 2546 2547 Perform post-installation checks and/or fixes on a system's 2548 configuration files. 2549 If no items are provided, a default set of checks or fixes is applied. 2550 2551 Options: 2552 -? Display this help, and exit. 2553 -a ARCH Set \$MACHINE_ARCH to ARCH. [${MACHINE_ARCH}] 2554 -d DEST_DIR Destination directory to check. [${DEST_DIR:-/}] 2555 -m MACHINE Set \$MACHINE to MACHINE. [${MACHINE}] 2556 -s SRC_ARG Location of the source files. This may be any of 2557 the following: 2558 -s SRC_DIR A directory that contains a NetBSD 2559 source tree. 2560 -s TGZ_DIR A directory in which one or both of 2561 "etc.tgz" and "xetc.tgz" have been 2562 extracted. 2563 -s TGZ_FILE A distribution set file such as 2564 "etc.tgz" or "xetc.tgz". 2565 May be specified multipled times. 2566 [${SRC_DIR:-/usr/src}] 2567 -x XSRC_DIR Location of the X11 source files. This must be 2568 a directory that contains a NetBSD xsrc tree. 2569 [${XSRC_DIR:-/usr/src/../xsrc}] 2570 2571 Supported values for OPERATION: 2572 help Display this help, and exit. 2573 list List available items. 2574 check ITEM ... Perform post-installation checks on ITEMs. 2575 diff [-bcenpuw] ITEM ... 2576 Similar to 'check' but also output difference of files, 2577 using diff with the provided options. 2578 fix ITEM ... Apply fixes that 'check' determines need to be applied. 2579 usage Display this help, and exit. 2580_USAGE_ 2581} 2582 2583usage() 2584{ 2585 help 1>&2 2586 exit 2 2587} 2588 2589 2590list() 2591{ 2592 echo "Default set of items (to apply if no items are provided by user):" 2593 echo " Item Description" 2594 echo " ---- -----------" 2595 for i in ${defaultitems}; do 2596 eval desc=\"\${desc_${i}}\" 2597 printf " %-20s %s\n" "${i}" "${desc}" 2598 done 2599 echo "Items disabled by default (must be requested explicitly):" 2600 echo " Item Description" 2601 echo " ---- -----------" 2602 for i in ${otheritems}; do 2603 eval desc=\"\${desc_${i}}\" 2604 printf " %-20s %s\n" "${i}" "${desc}" 2605 done 2606} 2607 2608 2609main() 2610{ 2611 DIRMODE=false # true if "-s" specified a directory 2612 ITEMS= # items to check|diff|fix. [${defaultitems}] 2613 N_SRC_ARGS=0 # number of "-s" args in SRC_ARGLIST 2614 SOURCEMODE=false # true if "-s" specified a source directory 2615 SRC_ARGLIST= # quoted list of one or more "-s" args 2616 SRC_DIR="${SRC_ARG}" # set default value for early usage() 2617 TGZLIST= # quoted list list of tgz files 2618 TGZMODE=false # true if "-s" specifies a tgz file 2619 XSRC_DIR="${SRC_ARG}/../xsrc" 2620 XSRC_DIR_FIX= 2621 2622 case "$(uname -s)" in 2623 Darwin) 2624 # case sensitive match for case insensitive fs 2625 file_exists_exact=file_exists_exact 2626 ;; 2627 *) 2628 file_exists_exact=: 2629 ;; 2630 esac 2631 2632 # Validate options. 2633 # 2634 while getopts :a:d:m:s:x: ch; do 2635 case "${ch}" in 2636 a) 2637 MACHINE_ARCH="${OPTARG}" 2638 ;; 2639 d) 2640 DEST_DIR="${OPTARG}" 2641 ;; 2642 m) 2643 MACHINE="${OPTARG}" 2644 ;; 2645 s) 2646 qarg="$(shell_quote "${OPTARG}")" 2647 N_SRC_ARGS=$(( $N_SRC_ARGS + 1 )) 2648 SRC_ARGLIST="${SRC_ARGLIST}${SRC_ARGLIST:+ }-s ${qarg}" 2649 if [ -f "${OPTARG}" ]; then 2650 # arg refers to a *.tgz file. 2651 # This may happen twice, for both 2652 # etc.tgz and xetc.tgz, so we build up a 2653 # quoted list in TGZLIST. 2654 TGZMODE=true 2655 TGZLIST="${TGZLIST}${TGZLIST:+ }${qarg}" 2656 # Note that, when TGZMODE is true, 2657 # SRC_ARG is used only for printing 2658 # human-readable messages. 2659 SRC_ARG="${TGZLIST}" 2660 elif [ -d "${OPTARG}" ]; then 2661 # arg refers to a directory. 2662 # It might be a source directory, or a 2663 # directory where the sets have already 2664 # been extracted. 2665 DIRMODE=true 2666 SRC_ARG="${OPTARG}" 2667 if [ -f "${OPTARG}/etc/Makefile" ]; then 2668 SOURCEMODE=true 2669 fi 2670 else 2671 err 2 "Invalid argument for -s option" 2672 fi 2673 ;; 2674 x) 2675 if [ -d "${OPTARG}" ]; then 2676 # arg refers to a directory. 2677 XSRC_DIR="${OPTARG}" 2678 XSRC_DIR_FIX="-x ${OPTARG} " 2679 else 2680 err 2 "Not a directory for -x option" 2681 fi 2682 ;; 2683 "?") 2684 if [ "${OPTARG}" = "?" ]; then 2685 help 2686 return # no further processing or validation 2687 fi 2688 warn "Unknown option -${OPTARG}" 2689 usage 2690 ;; 2691 2692 :) 2693 warn "Missing argument for option -${OPTARG}" 2694 usage 2695 ;; 2696 2697 *) 2698 err 3 "Unimplemented option -${ch}" 2699 ;; 2700 esac 2701 done 2702 shift $((${OPTIND} - 1)) 2703 if [ $# -eq 0 ] ; then 2704 warn "Missing operation" 2705 usage 2706 fi 2707 op="$1" 2708 shift 2709 2710 if [ "$N_SRC_ARGS" -gt 1 ] && $DIRMODE; then 2711 err 2 "Multiple -s args are allowed only with tgz files" 2712 fi 2713 if [ "$N_SRC_ARGS" -eq 0 ]; then 2714 # The default SRC_ARG was set elsewhere 2715 DIRMODE=true 2716 SOURCEMODE=true 2717 SRC_ARGLIST="-s $(shell_quote "${SRC_ARG}")" 2718 fi 2719 2720 # Validate 'diff' first, as it becomes 'check' 2721 # 2722 case "${op}" in 2723 2724 diff) 2725 op=check 2726 DIFF_STYLE=n # default style is RCS 2727 OPTIND=1 2728 while getopts :bcenpuw ch; do 2729 case "${ch}" in 2730 c|e|n|u) 2731 if [ "${DIFF_STYLE}" != "n" -a \ 2732 "${DIFF_STYLE}" != "${ch}" ]; then 2733 warn "diff: conflicting output style: -${ch}" 2734 usage 2735 fi 2736 DIFF_STYLE="${ch}" 2737 ;; 2738 b|p|w) 2739 DIFF_OPT="${DIFF_OPT} -${ch}" 2740 ;; 2741 "?") 2742 # NOTE: not supporting diff -? 2743 warn "diff: Unknown option -${OPTARG}" 2744 usage 2745 ;; 2746 :) 2747 warn "diff: Missing argument for option -${OPTARG}" 2748 usage 2749 ;; 2750 *) 2751 err 3 "diff: Unimplemented option -${ch}" 2752 ;; 2753 esac 2754 done 2755 shift $((${OPTIND} - 1)) 2756 ;; 2757 2758 esac 2759 2760 # Validate operation and items. 2761 # 2762 case "${op}" in 2763 2764 check|fix) 2765 ITEMS="$*" 2766 : ${ITEMS:="${defaultitems}"} 2767 2768 # ensure that all supplied items are valid 2769 # 2770 for i in ${ITEMS}; do 2771 eval desc=\"\${desc_${i}}\" 2772 [ -n "${desc}" ] || err 2 "Unsupported ${op} '"${i}"'" 2773 done 2774 ;; 2775 2776 help|usage) 2777 help 2778 return # no further processing or validation 2779 ;; 2780 2781 list) 2782 # processed below 2783 ;; 2784 2785 *) 2786 warn "Unknown operation '"${op}"'" 2787 usage 2788 ;; 2789 2790 esac 2791 2792 # 2793 # If '-s' arg or args specified tgz files, extract them 2794 # to a scratch directory. 2795 # 2796 if $TGZMODE; then 2797 ETCTGZDIR="${SCRATCHDIR}/etc.tgz" 2798 echo "Note: Creating temporary directory ${ETCTGZDIR}" 2799 if ! mkdir "${ETCTGZDIR}"; then 2800 err 2 "Can't create ${ETCTGZDIR}" 2801 fi 2802 ( # subshell to localise changes to "$@" 2803 eval "set -- ${TGZLIST}" 2804 for tgz in "$@"; do 2805 echo "Note: Extracting files from ${tgz}" 2806 cat "${tgz}" | ( 2807 cd "${ETCTGZDIR}" && 2808 tar -zxf - 2809 ) || err 2 "Can't extract ${tgz}" 2810 done 2811 ) 2812 SRC_DIR="${ETCTGZDIR}" 2813 else 2814 SRC_DIR="${SRC_ARG}" 2815 fi 2816 2817 [ -d "${SRC_DIR}" ] || err 2 "${SRC_DIR} is not a directory" 2818 [ -d "${DEST_DIR}" ] || err 2 "${DEST_DIR} is not a directory" 2819 [ -n "${MACHINE}" ] || err 2 "\${MACHINE} is not defined" 2820 [ -n "${MACHINE_ARCH}" ] || err 2 "\${MACHINE_ARCH} is not defined" 2821 if ! $SOURCEMODE && ! [ -f "${SRC_DIR}/etc/mtree/set.etc" ]; then 2822 err 2 "Files from the etc.tgz set are missing" 2823 fi 2824 2825 # If directories are /, clear them, so various messages 2826 # don't have leading "//". However, this requires 2827 # the use of ${foo:-/} to display the variables. 2828 # 2829 [ "${SRC_DIR}" = "/" ] && SRC_DIR="" 2830 [ "${DEST_DIR}" = "/" ] && DEST_DIR="" 2831 2832 detect_x11 2833 2834 # Perform operation. 2835 # 2836 case "${op}" in 2837 2838 check|fix) 2839 [ -n "${ITEMS}" ] || err 2 "${op}: missing items" 2840 2841 echo "Source directory: ${SRC_DIR:-/}" 2842 if $TGZMODE; then 2843 echo " (extracted from: ${SRC_ARG})" 2844 fi 2845 echo "Target directory: ${DEST_DIR:-/}" 2846 items_passed= 2847 items_failed= 2848 for i in ${ITEMS}; do 2849 echo "${i} ${op}:" 2850 ( eval do_${i} ${op} ) 2851 if [ $? -eq 0 ]; then 2852 items_passed="${items_passed} ${i}" 2853 else 2854 items_failed="${items_failed} ${i}" 2855 fi 2856 done 2857 2858 if [ "${op}" = "check" ]; then 2859 plural="checks" 2860 else 2861 plural="fixes" 2862 fi 2863 2864 echo "${PROGNAME} ${plural} passed:${items_passed}" 2865 echo "${PROGNAME} ${plural} failed:${items_failed}" 2866 if [ -n "${items_failed}" ]; then 2867 exitstatus=1; 2868 if [ "${op}" = "check" ]; then 2869 [ "$MACHINE" = "$(uname -m)" ] && m= || m=" -m $MACHINE" 2870 cat <<_Fix_me_ 2871To fix, run: 2872 ${HOST_SH} ${0} ${SRC_ARGLIST} ${XSRC_DIR_FIX}-d ${DEST_DIR:-/}$m fix${items_failed} 2873Note that this may overwrite local changes. 2874_Fix_me_ 2875 fi 2876 fi 2877 ;; 2878 2879 list) 2880 echo "Source directory: ${SRC_DIR:-/}" 2881 echo "Target directory: ${DEST_DIR:-/}" 2882 if $TGZMODE; then 2883 echo " (extracted from: ${SRC_ARG})" 2884 fi 2885 list 2886 ;; 2887 2888 *) 2889 # diff, help, usage handled during operation validation 2890 err 3 "Unimplemented operation '"${op}"'" 2891 ;; 2892 2893 esac 2894} 2895 2896if [ -n "$POSTINSTALL_FUNCTION" ]; then 2897 eval "$POSTINSTALL_FUNCTION" 2898 exit 0 2899fi 2900 2901# defaults 2902# 2903PROGNAME="${0##*/}" 2904SRC_ARG="/usr/src" 2905DEST_DIR="/" 2906: ${MACHINE:="$( uname -m )"} # assume native build if $MACHINE is not set 2907: ${MACHINE_ARCH:="$( uname -p )"}# assume native build if not set 2908 2909DIFF_STYLE= 2910DIFF_OPT= 2911NOT_FIXED=" (FIX MANUALLY)" 2912SCRATCHDIR="$( mkdtemp )" || err 2 "Can't create scratch directory" 2913trap "/bin/rm -rf \"\${SCRATCHDIR}\" ; exit 0" 1 2 3 15 # HUP INT QUIT TERM 2914 2915umask 022 2916exec 3>/dev/null 2917exec 4>/dev/null 2918exitstatus=0 2919 2920main "$@" 2921/bin/rm -rf "${SCRATCHDIR}" 2922exit $exitstatus 2923