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