[BACK]Return to postinstall.in CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.sbin / postinstall

Annotation of src/usr.sbin/postinstall/postinstall.in, Revision 1.30

1.1       christos    1: #!/bin/sh
                      2: #
1.30    ! riastrad    3: # $NetBSD: postinstall.in,v 1.29 2020/06/22 06:55:41 rin Exp $
1.1       christos    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: #      - 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:
                     68: err()
                     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:
                     79: warn()
                     80: {
                     81:        echo 1>&2 "${PROGNAME}: $*"
                     82: }
                     83:
                     84: msg()
                     85: {
                     86:        echo "  $*"
                     87: }
                     88:
                     89: mkdtemp()
                     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: #
                    115: shell_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}")"
                    159: bre_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: #
                    171: unprefix()
                    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: #
                    184: additem()
                    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: #
                    195: adddisableditem()
                    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: #
                    206: check_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: #
                    234: check_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
                    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 [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: #
                    304: populate_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 [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: #
                    362: compare_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: #
                    379: move_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: #
                    406: rcconf_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: #
                    440: rcvar_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: #
                    467: find_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: #
                    496: file_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: #
                    518: obsolete_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: #
                    560: obsolete_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:
1.5       christos  569: exclude()
                    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 libaries and exclude them
                    591: # from consideration for removal
                    592: #
                    593: exclude_libs() {
1.6       uwe       594:        local target="$(ls -l -d lib*.so.* 2> /dev/null \
1.5       christos  595:            | ${AWK} '{ print $11; }' \
                    596:            | ${SED} -e 's@.*/@@' | ${SORT} -u)"
                    597:        exclude -t ${target}
                    598: }
                    599:
1.1       christos  600: _obsolete_libs()
                    601: {
                    602:        dir="$1"
                    603:
                    604:        (
                    605:
                    606:        if [ ! -e "${DEST_DIR}/${dir}" ]
                    607:        then
                    608:                return 0
                    609:        fi
                    610:
                    611:        cd "${DEST_DIR}/${dir}" || err 2 "can't cd to ${DEST_DIR}/${dir}"
                    612:        echo lib*.so.* \
                    613:        | tr ' ' '\n' \
                    614:        | ${AWK} -v LibDir="${dir}/" '
                    615: #{
                    616:
                    617: function digit(v, c, n) { return (n <= c) ? v[n] : 0 }
                    618:
                    619: function checklib(results, line, regex) {
                    620:        if (! match(line, regex))
                    621:                return
                    622:        lib = substr(line, RSTART, RLENGTH)
                    623:        rev = substr($0, RLENGTH+1)
                    624:        if (! (lib in results)) {
                    625:                results[lib] = rev
                    626:                return
                    627:        }
                    628:        orevc = split(results[lib], orev, ".")
                    629:        nrevc = split(rev, nrev, ".")
                    630:        maxc = (orevc > nrevc) ? orevc : nrevc
                    631:        for (i = 1; i <= maxc; i++) {
                    632:                res = digit(orev, orevc, i) - digit(nrev, nrevc, i)
                    633:                if (res < 0) {
                    634:                        print LibDir lib results[lib]
                    635:                        results[lib] = rev
                    636:                        return
                    637:                } else if (res > 0) {
                    638:                        print LibDir lib rev
                    639:                        return
                    640:                }
                    641:        }
                    642: }
                    643:
                    644: /^lib.*\.so\.[0-9]+\.[0-9]+(\.[0-9]+)?(\.debug)?$/ {
                    645:        if (AllLibs)
                    646:                checklib(minor, $0, "^lib.*\\.so\\.")
                    647:        else
                    648:                checklib(found, $0, "^lib.*\\.so\\.[0-9]+\\.")
                    649: }
                    650:
                    651: /^lib.*\.so\.[0-9]+$/ {
                    652:        if (AllLibs)
                    653:                checklib(major, $0, "^lib.*\\.so\\.")
                    654: }
                    655:
1.5       christos  656: #}' | exclude_libs
1.1       christos  657:
                    658:        )
                    659: }
                    660:
                    661: # obsolete_stand dir
                    662: #      Prints the names of all obsolete files and subdirs below the
                    663: #      provided dir.  dir should be something like /stand/${MACHINE}.
                    664: #      The input dir and all output paths are interpreted
                    665: #      relative to ${DEST_DIR}.
                    666: #
                    667: #      Assumes that the numerically largest subdir is current, and all
                    668: #      others are obsolete.
                    669: #
                    670: obsolete_stand()
                    671: {
                    672:        [ $# -eq 1 ] || err 3 "USAGE: obsolete_stand dir"
                    673:        local dir="$1"
                    674:        local subdir
                    675:
                    676:        if ! [ -d "${DEST_DIR}${dir}" ]; then
                    677:                msg "${DEST_DIR}${dir} doesn't exist; can't check for obsolete files"
                    678:                return 1
                    679:        fi
                    680:
                    681:        ( cd "${DEST_DIR}${dir}" && ls -1d [0-9]*[0-9]/. ) \
                    682:        | ${GREP} -v '[^0-9./]' \
                    683:        | sort -t. -r -n -k1,1 -k2,2 -k3,3 \
                    684:        | tail -n +2 \
                    685:        | while read subdir ; do
                    686:                subdir="${subdir%/.}"
                    687:                find "${DEST_DIR}${dir}/${subdir}" -depth -print
                    688:        done \
                    689:        | unprefix "${DEST_DIR}"
                    690: }
                    691:
                    692: # modify_file op srcfile scratchfile awkprog
                    693: #      Apply awkprog to srcfile sending output to scratchfile, and
                    694: #      if appropriate replace srcfile with scratchfile.
                    695: #
                    696: modify_file()
                    697: {
                    698:        [ $# -eq 4 ] || err 3 "USAGE: modify_file op file scratch awkprog"
                    699:
                    700:        _mfop="$1"
                    701:        _mffile="$2"
                    702:        _mfscratch="$3"
                    703:        _mfprog="$4"
                    704:        _mffailed=0
                    705:
                    706:        ${AWK} "${_mfprog}" < "${_mffile}" > "${_mfscratch}"
                    707:        if ! cmp -s "${_mffile}" "${_mfscratch}"; then
                    708:                diff "${_mffile}" "${_mfscratch}" > "${_mfscratch}.diffs"
                    709:                if [ "${_mfop}" = "check" ]; then
                    710:                        msg "${_mffile} needs the following changes:"
                    711:                        _mffailed=1
                    712:                elif ! rm -f "${_mffile}" ||
                    713:                     ! cp -f "${_mfscratch}" "${_mffile}"; then
                    714:                        msg "${_mffile} changes not applied:"
                    715:                        _mffailed=1
                    716:                else
                    717:                        msg "${_mffile} changes applied:"
                    718:                fi
                    719:                while read _line; do
                    720:                        msg "   ${_line}"
                    721:                done < "${_mfscratch}.diffs"
                    722:        fi
                    723:        return ${_mffailed}
                    724: }
                    725:
                    726:
                    727: # contents_owner op directory user group
                    728: #      Make sure directory and contents are owned (and group-owned)
                    729: #      as specified.
                    730: #
                    731: contents_owner()
                    732: {
                    733:        [ $# -eq 4 ] || err 3 "USAGE: contents_owner op dir user group"
                    734:
                    735:        _op="$1"
                    736:        _dir="$2"
                    737:        _user="$3"
                    738:        _grp="$4"
                    739:
                    740:        if [ "${_op}" = "check" ]; then
1.18      roy       741:                _files=$(find "${_dir}" \( \( ! -user "${_user}" \) -o \
                    742:                                \( ! -group "${_grp}" \) \) )
                    743:                _error=$?
                    744:                if [ ! -z "$_files" ] || [ $_error != 0 ]; then
                    745:                        msg "${_dir} and contents not all owned by" \
                    746:                            "${_user}:${_grp}"
1.1       christos  747:                        return 1
                    748:                else
                    749:                        return 0
                    750:                fi
                    751:        elif [ "${_op}" = "fix" ]; then
                    752:                find "${_dir}" \( \( ! -user "${_user}" \) -o \
1.20      roy       753:                \( ! -group "${_grp}" \) \) \
                    754:                -exec chown "${_user}:${_grp}" -- {} \;
1.1       christos  755:        fi
                    756: }
                    757:
                    758: # get_makevar var [var ...]
                    759: #      Retrieve the value of a user-settable system make variable
                    760: get_makevar()
                    761: {
                    762:        $SOURCEMODE || err 3 "get_makevar must be used in source mode"
                    763:        [ $# -eq 0 ] && err 3 "USAGE: get_makevar var [var ...]"
                    764:
                    765:        for _var in "$@"; do
                    766:                _value="$(echo '.include <bsd.own.mk>' | \
                    767:                    ${MAKE} -f - -V "\${${_var}}")"
                    768:
                    769:                eval ${_var}=\"\${_value}\"
                    770:        done
                    771: }
                    772:
                    773: # detect_x11
                    774: #      Detect if X11 components should be analysed and set values of
                    775: #      relevant variables.
                    776: detect_x11()
                    777: {
                    778:        if $SOURCEMODE; then
                    779:                get_makevar MKX11 X11ROOTDIR X11SRCDIR
                    780:        else
                    781:                if [ -f "${SRC_DIR}/etc/mtree/set.xetc" ]; then
                    782:                        MKX11=yes
                    783:                        X11ROOTDIR=/this/value/isnt/used/yet
                    784:                else
                    785:                        MKX11=no
                    786:                        X11ROOTDIR=
                    787:                fi
                    788:                X11SRCDIR=/nonexistent/xsrc
                    789:        fi
                    790: }
                    791:
                    792: #
                    793: #      find out where MAKEDEV lives, set MAKEDEV_DIR appropriately
                    794: #
                    795: find_makedev()
                    796: {
                    797:        if [ -e "${DEST_DIR}/dev/MAKEDEV" ]; then
                    798:                MAKEDEV_DIR="${DEST_DIR}/dev"
                    799:        elif [ -e "${DEST_DIR}/etc/MAKEDEV" ]; then
                    800:                MAKEDEV_DIR="${DEST_DIR}/etc"
                    801:        else
                    802:                MAKEDEV_DIR="${DEST_DIR}/dev"
                    803:        fi
                    804: }
                    805:
                    806:
                    807: #
                    808: #      items
                    809: #      -----
                    810: #
                    811:
                    812: #
                    813: #      Bluetooth
                    814: #
                    815:
                    816: additem bluetooth "Bluetooth configuration is up to date"
                    817: do_bluetooth()
                    818: {
                    819:        [ -n "$1" ] || err 3 "USAGE: do_bluetooth fix|check"
                    820:        op="$1"
                    821:        failed=0
                    822:
                    823:        populate_dir "${op}" true \
                    824:                "${SRC_DIR}/etc/bluetooth" "${DEST_DIR}/etc/bluetooth" 644 \
                    825:                hosts protocols btattach.conf btdevctl.conf
                    826:        failed=$(( ${failed} + $? ))
                    827:
                    828:        move_file "${op}" "${DEST_DIR}/var/db/btdev.xml" \
                    829:                        "${DEST_DIR}/var/db/btdevctl.plist"
                    830:        failed=$(( ${failed} + $? ))
                    831:
                    832:        notfixed=""
                    833:        if [ "${op}" = "fix" ]; then
                    834:                notfixed="${NOT_FIXED}"
                    835:        fi
                    836:        for _v in btattach btconfig btdevctl; do
                    837:                if rcvar_is_enabled "${_v}"; then
                    838:                        msg \
                    839:     "${_v} is obsolete in rc.conf(5)${notfixed}: use bluetooth=YES"
                    840:                        failed=$(( ${failed} + 1 ))
                    841:                fi
                    842:        done
                    843:
                    844:        return ${failed}
                    845: }
                    846:
1.24      christos  847: fixblock() {
1.29      rin       848:        local op="$1"
                    849:        local target="${DEST_DIR}$2"
                    850:
                    851:        if [ ! -f "${target}" ]; then
                    852:                continue
                    853:        fi
                    854:
                    855:        if ${GREP} '[bB]lack' "${target}" > /dev/null; then
                    856:                if [ "$1" = "check" ]; then
                    857:                        msg "Fix old configuration file(s)."
                    858:                        return 1
                    859:                else
                    860:                        local p=$(${STAT} -f %Lp "${target}")
                    861:                        chmod u+w "${target}" || return 1
                    862:                        ${SED} -i -e 's/\([bB]\)lack/\1lock/g' "${target}"
                    863:                        chmod "${p}" "${target}"
1.24      christos  864:                fi
1.29      rin       865:        fi
1.24      christos  866: }
                    867:
                    868: #
                    869: #      blocklist update
                    870: #
                    871: additem blocklist "rename old files to blocklist"
                    872: do_blocklist()
                    873: {
1.29      rin       874:        [ -n "$1" ] || err 3 "USAGE: do_blocklist  fix|check"
                    875:        local op="$1"
1.30    ! riastrad  876:
1.24      christos  877:        # if we are actually using blocklistd
1.29      rin       878:        for i in /var/db/blacklist.db /etc/blacklistd.conf; do
                    879:                local old="${DEST_DIR}${i}"
                    880:                if [ ! -f "${old}" ]; then
                    881:                        continue
                    882:                elif [ "$1" = "check" ]; then
                    883:                        msg "Rename old file(s)."
                    884:                        return 1
                    885:                fi
                    886:                local new=$(echo "${old}" | ${SED} s/black/block/)
                    887:                mv "${old}" "${new}" || return 1
                    888:        done
1.24      christos  889:
1.29      rin       890:        for i in /etc/rc.conf /etc/npf.conf /etc/blocklistd.conf \
                    891:            /etc/defaults/rc.conf; do
                    892:                fixblock "${op}" "${i}" || return 1
                    893:        done
1.24      christos  894: }
                    895:
1.1       christos  896: #
                    897: #      ddbonpanic
                    898: #
                    899: additem ddbonpanic "verify ddb.onpanic is configured in sysctl.conf"
                    900: do_ddbonpanic()
                    901: {
                    902:        [ -n "$1" ] || err 3 "USAGE: do_ddbonpanic  fix|check"
                    903:
                    904:        if ${GREP} -E '^#*[[:space:]]*ddb\.onpanic[[:space:]]*\??=[[:space:]]*[[:digit:]]+' \
                    905:                "${DEST_DIR}/etc/sysctl.conf" >/dev/null 2>&1
                    906:        then
                    907:                result=0
                    908:        else
                    909:                if [ "$1" = check ]; then
                    910:                        msg \
                    911:     "The ddb.onpanic behaviour is not explicitly specified in /etc/sysctl.conf"
                    912:                        result=1
                    913:                else
                    914:                        echo >> "${DEST_DIR}/etc/sysctl.conf"
                    915:                        ${SED} < "${SRC_DIR}/etc/sysctl.conf" \
                    916:                           -e '/^ddb\.onpanic/q' | \
                    917:                               ${SED} -e '1,/^$/d' >> \
                    918:                            "${DEST_DIR}/etc/sysctl.conf"
                    919:                        result=$?
                    920:                fi
                    921:        fi
                    922:        return ${result}
                    923: }
                    924:
                    925: #
                    926: #      defaults
                    927: #
                    928: additem defaults "/etc/defaults/ being up to date"
                    929: do_defaults()
                    930: {
                    931:        [ -n "$1" ] || err 3 "USAGE: do_defaults  fix|check"
                    932:        local op="$1"
                    933:        local failed=0
                    934:        local etcsets=$(getetcsets)
                    935:
                    936:        local rc_exclude_scripts=""
                    937:        if $SOURCEMODE; then
                    938:                # For most architectures rc.conf(5) should be the same as the
                    939:                # one obtained from a source directory, except for the ones
                    940:                # that have an append file for it.
                    941:                local rc_conf_app="${SRC_DIR}/etc/etc.${MACHINE}/rc.conf.append"
                    942:                if [ -f "${rc_conf_app}" ]; then
                    943:                        rc_exclude_scripts="rc.conf"
                    944:
                    945:                        # Generate and compare the correct rc.conf(5) file
                    946:                        mkdir "${SCRATCHDIR}/defaults"
                    947:
                    948:                        cat "${SRC_DIR}/etc/defaults/rc.conf" "${rc_conf_app}" \
                    949:                            > "${SCRATCHDIR}/defaults/rc.conf"
                    950:
                    951:                        compare_dir "${op}" "${SCRATCHDIR}/defaults" \
                    952:                            "${DEST_DIR}/etc/defaults" \
                    953:                            444 \
                    954:                            "rc.conf"
                    955:                        failed=$(( ${failed} + $? ))
                    956:                fi
                    957:        fi
                    958:
                    959:        find_file_in_dirlist pf.boot.conf "pf.boot.conf" \
                    960:            "${SRC_DIR}/usr.sbin/pf/etc/defaults" "${SRC_DIR}/etc/defaults" \
                    961:            || return 1
                    962:        # ${dir} is set by find_file_in_dirlist()
                    963:        compare_dir "$op" "${dir}" "${DEST_DIR}/etc/defaults" 444 pf.boot.conf
                    964:        failed=$(( ${failed} + $? ))
                    965:
                    966:        rc_exclude_scripts="${rc_exclude_scripts} pf.boot.conf"
                    967:
                    968:        local rc_default_conf_files="$(select_set_files /etc/defaults/ \
                    969:            "/etc/defaults/\([^[:space:]]*\.conf\)" ${etcsets} | \
                    970:            exclude ${rc_exclude_scripts})"
                    971:        compare_dir "$op" "${SRC_DIR}/etc/defaults" "${DEST_DIR}/etc/defaults" \
                    972:                444 \
                    973:                ${rc_default_conf_files}
                    974:        failed=$(( ${failed} + $? ))
                    975:
                    976:
                    977:        return ${failed}
                    978: }
                    979:
                    980: #
                    981: #      dhcpcd
                    982: #
                    983: additem dhcpcd "dhcpcd configuration is up to date"
                    984: do_dhcpcd()
                    985: {
                    986:        [ -n "$1" ] || err 3 "USAGE: do_dhcpcd fix|check"
                    987:        op="$1"
                    988:        failed=0
                    989:
                    990:        find_file_in_dirlist dhcpcd.conf "dhcpcd.conf" \
                    991:            "${SRC_DIR}/external/bsd/dhcpcd/dist/src" \
                    992:            "${SRC_DIR}/etc" || return 1
                    993:                        # ${dir} is set by find_file_in_dirlist()
                    994:        populate_dir "$op" true "${dir}" "${DEST_DIR}/etc" 644 dhcpcd.conf
                    995:        failed=$(( ${failed} + $? ))
                    996:
1.22      roy       997:        check_dir "${op}" "${DEST_DIR}/var/db/dhcpcd" 755
1.1       christos  998:        failed=$(( ${failed} + $? ))
                    999:
                   1000:        move_file "${op}" \
                   1001:                "${DEST_DIR}/etc/dhcpcd.duid" \
1.22      roy      1002:                "${DEST_DIR}/var/db/dhcpcd/duid"
1.1       christos 1003:        failed=$(( ${failed} + $? ))
                   1004:
                   1005:        move_file "${op}" \
                   1006:                "${DEST_DIR}/etc/dhcpcd.secret" \
1.22      roy      1007:                "${DEST_DIR}/var/db/dhcpcd/secret"
1.1       christos 1008:        failed=$(( ${failed} + $? ))
                   1009:
                   1010:        move_file "${op}" \
                   1011:                "${DEST_DIR}/var/db/dhcpcd-rdm.monotonic" \
1.22      roy      1012:                "${DEST_DIR}/var/db/dhcpcd/rdm_monotonic"
1.1       christos 1013:        failed=$(( ${failed} + $? ))
                   1014:
                   1015:        for lease in "${DEST_DIR}/var/db/dhcpcd-"*.lease*; do
                   1016:                [ -f "${lease}" ] || continue
                   1017:                new_lease=$(basename "${lease}" | ${SED} -e 's/dhcpcd-//')
1.22      roy      1018:                new_lease="${DEST_DIR}/var/db/dhcpcd/${new_lease}"
1.1       christos 1019:                move_file "${op}" "${lease}" "${new_lease}"
                   1020:                failed=$(( ${failed} + $? ))
                   1021:        done
                   1022:
1.22      roy      1023:        chroot_dir="${DEST_DIR}/var/chroot/dhcpcd"
1.16      roy      1024:        move_file "${op}" \
1.22      roy      1025:                "${chroot_dir}/var/db/dhcpcd/duid" \
                   1026:                "${DEST_DIR}/var/db/dhcpcd/duid"
1.16      roy      1027:        failed=$(( ${failed} + $? ))
                   1028:
                   1029:        move_file "${op}" \
1.22      roy      1030:                "${chroot_dir}/var/db/dhcpcd/secret" \
                   1031:                "${DEST_DIR}/var/db/dhcpcd/secret"
1.16      roy      1032:        failed=$(( ${failed} + $? ))
                   1033:
                   1034:        move_file "${op}" \
1.22      roy      1035:                "${chroot_dir}/var/db/dhcpcd/rdm_monotonic" \
                   1036:                "${DEST_DIR}/var/db/dhcpcd/rdm_monotonic"
1.16      roy      1037:        failed=$(( ${failed} + $? ))
                   1038:
1.22      roy      1039:        for lease in "${chroot_dir}/var/db/dhcpcd/"*.lease*; do
1.16      roy      1040:                [ -f "${lease}" ] || continue
1.22      roy      1041:                new_lease="${DEST_DIR}/var/db/dhcpcd/$(basename ${lease})"
1.16      roy      1042:                move_file "${op}" "${lease}" "${new_lease}"
                   1043:                failed=$(( ${failed} + $? ))
                   1044:        done
                   1045:
1.22      roy      1046:        # Ensure chroot is now empty
                   1047:        for dir in \
1.23      roy      1048:                $(find ${chroot_dir} ! -type d) \
1.22      roy      1049:                $(find ${chroot_dir} -type d -mindepth 1 | sort -r)
                   1050:        do
                   1051:                echo "/var/chroot/dhcpcd${dir##${chroot_dir}}"
                   1052:        done | obsolete_paths "${op}"
                   1053:        failed=$(( ${failed} + $? ))
                   1054:
                   1055:        contents_owner "${op}" "${DEST_DIR}/var/db/dhcpcd" root wheel
1.16      roy      1056:        failed=$(( ${failed} + $? ))
                   1057:
1.1       christos 1058:        return ${failed}
                   1059: }
                   1060:
                   1061: #
                   1062: #      dhcpcdrundir
                   1063: #
                   1064: additem dhcpcdrundir "accidentaly created /@RUNDIR@ does not exist"
                   1065: do_dhcpcdrundir()
                   1066: {
                   1067:        [ -n "$1" ] || err 3 "USAGE: do_dhcpcdrundir fix|check"
                   1068:        op="$1"
                   1069:        failed=0
                   1070:
                   1071:        if [ -d "${DEST_DIR}/@RUNDIR@" ]; then
                   1072:                if [ "${op}" = "check" ]; then
                   1073:                        msg "Remove eroneously created /@RUNDIR@"
                   1074:                        failed=1
                   1075:                elif ! rm -r "${DEST_DIR}/@RUNDIR@"; then
                   1076:                        msg "Failed to remove ${DEST_DIR}/@RUNDIR@"
                   1077:                        failed=1
                   1078:                else
                   1079:                        msg "Removed eroneously created ${DEST_DIR}/@RUNDIR@"
                   1080:                fi
                   1081:        fi
                   1082:        return ${failed}
                   1083: }
                   1084:
                   1085: #
                   1086: #      envsys
                   1087: #
                   1088: additem envsys "envsys configuration is up to date"
                   1089: do_envsys()
                   1090: {
                   1091:        [ -n "$1" ] || err 3 "USAGE: do_envsys fix|check"
1.3       christos 1092:        local op="$1"
                   1093:        local failed=0
                   1094:        local etcsets=$(getetcsets)
1.1       christos 1095:
                   1096:        populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \
                   1097:                envsys.conf
                   1098:        failed=$(( ${failed} + $? ))
                   1099:
1.3       christos 1100:        local powerd_scripts="$(select_set_files /etc/powerd/scripts/ \
                   1101:            "/etc/powerd/scripts/\([^[:space:]/]*\)" ${etcsets})"
                   1102:
1.1       christos 1103:        populate_dir "$op" true "${SRC_DIR}/etc/powerd/scripts" \
1.3       christos 1104:                "${DEST_DIR}/etc/powerd/scripts" \
                   1105:                555 \
                   1106:                ${powerd_scripts}
1.1       christos 1107:        failed=$(( ${failed} + $? ))
                   1108:
                   1109:        return ${failed}
                   1110: }
                   1111:
                   1112: #
1.13      christos 1113: #      autofs config files
                   1114: #
                   1115: additem autofsconfig "automounter configuration files"
                   1116: do_autofsconfig()
                   1117: {
                   1118:        [ -n "$1" ] || err 3 "USAGE: do_autofsconfig fix|check"
                   1119:        local autofs_files="
                   1120: include_ldap
                   1121: include_nis
                   1122: special_hosts
                   1123: special_media
                   1124: special_noauto
1.28      riastrad 1125: special_null
1.13      christos 1126: "
                   1127:        op="$1"
                   1128:        failed=0
                   1129:        if [ "$op" = "fix" ]; then
                   1130:                mkdir -p "${DEST_DIR}/etc/autofs"
                   1131:        fi
                   1132:        failed=$(( ${failed} + $? ))
                   1133:        populate_dir "$op" false "${SRC_DIR}/etc" \
                   1134:            "${DEST_DIR}/etc" \
1.14      christos 1135:            644 \
1.13      christos 1136:            auto_master
                   1137:        failed=$(( ${failed} + $? ))
                   1138:        populate_dir "$op" false "${SRC_DIR}/etc/autofs" \
                   1139:            "${DEST_DIR}/etc/autofs" \
1.14      christos 1140:            644 \
1.13      christos 1141:            ${autofs_files}
                   1142:        return ${failed}
                   1143: }
                   1144:
                   1145:
                   1146: #
1.1       christos 1147: #      X11 fontconfig
                   1148: #
                   1149: additem fontconfig "X11 font configuration is up to date"
                   1150: do_fontconfig()
                   1151: {
                   1152:        [ -n "$1" ] || err 3 "USAGE: do_fontconfig fix|check"
                   1153:        op="$1"
                   1154:        failed=0
                   1155:
                   1156:        # First, check for updates we can handle.
                   1157:        if ! $SOURCEMODE; then
                   1158:                FONTCONFIG_DIR="${SRC_DIR}/etc/fonts/conf.avail"
                   1159:        else
                   1160:                FONTCONFIG_DIR="${XSRC_DIR}/external/mit/fontconfig/dist/conf.d"
                   1161:        fi
                   1162:
                   1163:        if [ ! -d "${FONTCONFIG_DIR}" ]; then
                   1164:                msg "${FONTCONFIG_DIR} is not a directory; skipping check"
                   1165:                return 0
                   1166:        fi
1.4       christos 1167:        local regular_fonts="
                   1168: 10-autohint.conf
                   1169: 10-no-sub-pixel.conf
                   1170: 10-scale-bitmap-fonts.conf
                   1171: 10-sub-pixel-bgr.conf
                   1172: 10-sub-pixel-rgb.conf
                   1173: 10-sub-pixel-vbgr.conf
                   1174: 10-sub-pixel-vrgb.conf
                   1175: 10-unhinted.conf
                   1176: 11-lcdfilter-default.conf
                   1177: 11-lcdfilter-legacy.conf
                   1178: 11-lcdfilter-light.conf
                   1179: 20-unhint-small-vera.conf
                   1180: 25-unhint-nonlatin.conf
                   1181: 30-metric-aliases.conf
                   1182: 40-nonlatin.conf
                   1183: 45-generic.conf
                   1184: 45-latin.conf
                   1185: 49-sansserif.conf
                   1186: 50-user.conf
                   1187: 51-local.conf
                   1188: 60-generic.conf
                   1189: 60-latin.conf
                   1190: 65-fonts-persian.conf
                   1191: 65-khmer.conf
                   1192: 65-nonlatin.conf
                   1193: 69-unifont.conf
                   1194: 70-no-bitmaps.conf
                   1195: 70-yes-bitmaps.conf
                   1196: 80-delicious.conf
                   1197: 90-synthetic.conf
                   1198: "
                   1199:        populate_dir "$op" false "${FONTCONFIG_DIR}" \
                   1200:            "${DEST_DIR}/etc/fonts/conf.avail" \
                   1201:            444 \
                   1202:            ${regular_fonts}
1.1       christos 1203:        failed=$(( ${failed} + $? ))
                   1204:
                   1205:        if ! $SOURCEMODE; then
                   1206:                FONTS_DIR="${SRC_DIR}/etc/fonts"
                   1207:        else
                   1208:                FONTS_DIR="${SRC_DIR}/external/mit/xorg/lib/fontconfig/etc"
                   1209:        fi
                   1210:
                   1211:        populate_dir "$op" false "${FONTS_DIR}" "${DEST_DIR}/etc/fonts" 444 \
                   1212:                fonts.conf
                   1213:        failed=$(( ${failed} + $? ))
                   1214:
                   1215:        # We can't modify conf.d easily; someone might have removed a file.
                   1216:
                   1217:        # Look for old files that need to be deleted.
1.4       christos 1218:        obsolete_fonts="
                   1219: 10-autohint.conf
                   1220: 10-no-sub-pixel.conf
                   1221: 10-sub-pixel-bgr.conf
                   1222: 10-sub-pixel-rgb.conf
                   1223: 10-sub-pixel-vbgr.conf
                   1224: 10-sub-pixel-vrgb.conf
                   1225: 10-unhinted.conf
                   1226: 25-unhint-nonlatin.conf
                   1227: 65-khmer.conf
                   1228: 70-no-bitmaps.conf
                   1229: 70-yes-bitmaps.conf
                   1230: "
                   1231:        failed_fonts=""
                   1232:        for i in ${obsolete_fonts}; do
                   1233:            if [ -f "${DEST_DIR}/etc/fonts/conf.d/$i" ]; then
                   1234:                    conf_d_failed=1
                   1235:                    failed_fonts="$failed_fonts $i"
                   1236:            fi
                   1237:        done
1.1       christos 1238:
1.4       christos 1239:        if [ -n "$failed_fonts" ]; then
1.1       christos 1240:                msg \
1.4       christos 1241:     "Broken fontconfig configuration found; please delete these files:"
                   1242:                msg "[$failed_fonts]"
                   1243:                failed=$(( ${failed} + 1 ))
1.1       christos 1244:        fi
                   1245:
                   1246:        return ${failed}
                   1247: }
                   1248:
                   1249: #
                   1250: #      gid
                   1251: #
                   1252: additem gid "required groups in /etc/group"
                   1253: do_gid()
                   1254: {
                   1255:        [ -n "$1" ] || err 3 "USAGE: do_gid  fix|check"
                   1256:
                   1257:        check_ids "$1" groups "${DEST_DIR}/etc/group" \
                   1258:            "${SRC_DIR}/etc/group" 14 \
                   1259:            named ntpd sshd SKIP _pflogd _rwhod staff _proxy _timedc \
                   1260:            _sdpd _httpd _mdnsd _tests _tcpdump _tss _gpio _rtadvd SKIP \
1.17      roy      1261:            _unbound _nsd nvmm _dhcpcd
1.1       christos 1262: }
                   1263:
                   1264: #
                   1265: #      gpio
                   1266: #
                   1267: additem gpio "gpio configuration is up to date"
                   1268: do_gpio()
                   1269: {
                   1270:        [ -n "$1" ] || err 3 "USAGE: do_gpio fix|check"
                   1271:        op="$1"
                   1272:        failed=0
                   1273:
                   1274:        populate_dir "$op" true "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \
                   1275:                gpio.conf
                   1276:        failed=$(( ${failed} + $? ))
                   1277:
                   1278:        return ${failed}
                   1279: }
                   1280:
                   1281: #
                   1282: #      hosts
                   1283: #
                   1284: additem hosts "/etc/hosts being up to date"
                   1285: do_hosts()
                   1286: {
                   1287:        [ -n "$1" ] || err 3 "USAGE: do_hosts  fix|check"
                   1288:
                   1289:        modify_file "$1" "${DEST_DIR}/etc/hosts" "${SCRATCHDIR}/hosts" '
                   1290:                /^(127\.0\.0\.1|::1)[   ]+[^\.]*$/ {
                   1291:                        print $0, "localhost."
                   1292:                        next
                   1293:                }
                   1294:                { print }
                   1295:        '
                   1296:        return $?
                   1297: }
                   1298:
                   1299: #
                   1300: #      iscsi
                   1301: #
                   1302: additem iscsi "/etc/iscsi is populated"
                   1303: do_iscsi()
                   1304: {
                   1305:        [ -n "$1" ] || err 3 "USAGE: do_iscsi  fix|check"
                   1306:
                   1307:        populate_dir "${op}" true \
                   1308:            "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 600 auths
                   1309:        populate_dir "${op}" true \
                   1310:            "${SRC_DIR}/etc/iscsi" "${DEST_DIR}/etc/iscsi" 644 targets
                   1311:        return $?
                   1312: }
                   1313:
                   1314: #
                   1315: #      makedev
                   1316: #
                   1317: additem makedev "/dev/MAKEDEV being up to date"
                   1318: do_makedev()
                   1319: {
                   1320:        [ -n "$1" ] || err 3 "USAGE: do_makedev   fix|check"
                   1321:        failed=0
                   1322:
                   1323:        if [ -f "${SRC_DIR}/etc/MAKEDEV.tmpl" ]; then
                   1324:                        # generate MAKEDEV from source if source is available
                   1325:                env MACHINE="${MACHINE}" \
                   1326:                    MACHINE_ARCH="${MACHINE_ARCH}" \
                   1327:                    NETBSDSRCDIR="${SRC_DIR}" \
                   1328:                    ${AWK} -f "${SRC_DIR}/etc/MAKEDEV.awk" \
                   1329:                    "${SRC_DIR}/etc/MAKEDEV.tmpl" > "${SCRATCHDIR}/MAKEDEV"
                   1330:        fi
                   1331:
                   1332:        find_file_in_dirlist MAKEDEV "MAKEDEV" \
                   1333:            "${SCRATCHDIR}" "${SRC_DIR}/dev" \
                   1334:            || return 1
                   1335:                        # ${dir} is set by find_file_in_dirlist()
                   1336:        find_makedev
                   1337:        compare_dir "$1" "${dir}" "${MAKEDEV_DIR}" 555 MAKEDEV
                   1338:        failed=$(( ${failed} + $? ))
                   1339:
                   1340:        find_file_in_dirlist MAKEDEV.local "MAKEDEV.local" \
                   1341:            "${SRC_DIR}/etc" "${SRC_DIR}/dev" \
                   1342:            || return 1
                   1343:                        # ${dir} is set by find_file_in_dirlist()
                   1344:        compare_dir "$1" "${dir}" "${DEST_DIR}/dev" 555 MAKEDEV.local
                   1345:        failed=$(( ${failed} + $? ))
                   1346:
                   1347:        return ${failed}
                   1348: }
                   1349:
                   1350: #
                   1351: #      motd
                   1352: #
                   1353: additem motd "contents of motd"
                   1354: do_motd()
                   1355: {
                   1356:        [ -n "$1" ] || err 3 "USAGE: do_motd  fix|check"
                   1357:
                   1358:        if ${GREP} -i 'http://www.NetBSD.org/Misc/send-pr.html' \
                   1359:                "${DEST_DIR}/etc/motd" >/dev/null 2>&1 \
1.15      nakayama 1360:            || ${GREP} -i 'https*://www.NetBSD.org/support/send-pr.html' \
1.1       christos 1361:                "${DEST_DIR}/etc/motd" >/dev/null 2>&1
                   1362:        then
                   1363:                tmp1="$(mktemp /tmp/postinstall.motd.XXXXXXXX)"
                   1364:                tmp2="$(mktemp /tmp/postinstall.motd.XXXXXXXX)"
                   1365:                ${SED} '1,2d' <"${SRC_DIR}/etc/motd" >"${tmp1}"
                   1366:                ${SED} '1,2d' <"${DEST_DIR}/etc/motd" >"${tmp2}"
                   1367:
                   1368:                if [ "$1" = check ]; then
                   1369:                        cmp -s "${tmp1}" "${tmp2}"
                   1370:                        result=$?
                   1371:                        if [ "${result}" -ne 0 ]; then
                   1372:                                msg \
                   1373:     "Bug reporting messages do not seem to match the installed release"
                   1374:                        fi
                   1375:                else
                   1376:                        head -n 2 "${DEST_DIR}/etc/motd" >"${tmp1}"
                   1377:                        ${SED} '1,2d' <"${SRC_DIR}/etc/motd" >>"${tmp1}"
                   1378:                        cp "${tmp1}" "${DEST_DIR}/etc/motd"
                   1379:                        result=0
                   1380:                fi
                   1381:
                   1382:                rm -f "${tmp1}" "${tmp2}"
                   1383:        else
                   1384:                result=0
                   1385:        fi
                   1386:
                   1387:        return ${result}
                   1388: }
                   1389:
                   1390: #
                   1391: #      mtree
                   1392: #
                   1393: additem mtree "/etc/mtree/ being up to date"
                   1394: do_mtree()
                   1395: {
                   1396:        [ -n "$1" ] || err 3 "USAGE: do_mtree  fix|check"
                   1397:        failed=0
                   1398:
                   1399:        compare_dir "$1" "${SRC_DIR}/etc/mtree" "${DEST_DIR}/etc/mtree" 444 special
                   1400:        failed=$(( ${failed} + $? ))
                   1401:
                   1402:        if ! $SOURCEMODE; then
                   1403:                MTREE_DIR="${SRC_DIR}/etc/mtree"
                   1404:        else
                   1405:                /bin/rm -rf "${SCRATCHDIR}/obj"
                   1406:                mkdir "${SCRATCHDIR}/obj"
                   1407:                ${MAKE} -s -C "${SRC_DIR}/etc/mtree" TOOL_AWK="${AWK}" \
                   1408:                    MAKEOBJDIR="${SCRATCHDIR}/obj" emit_dist_file > \
                   1409:                    "${SCRATCHDIR}/NetBSD.dist"
                   1410:                MTREE_DIR="${SCRATCHDIR}"
                   1411:                /bin/rm -rf "${SCRATCHDIR}/obj"
                   1412:        fi
                   1413:        compare_dir "$1" "${MTREE_DIR}" "${DEST_DIR}/etc/mtree" 444 NetBSD.dist
                   1414:        failed=$(( ${failed} + $? ))
                   1415:
                   1416:        return ${failed}
                   1417: }
                   1418:
                   1419: #
                   1420: #      named
                   1421: #
                   1422: additem named "named configuration update"
                   1423: do_named()
                   1424: {
                   1425:        [ -n "$1" ] || err 3 "USAGE: do_named  fix|check"
                   1426:        op="$1"
                   1427:
                   1428:        move_file "${op}" \
                   1429:                "${DEST_DIR}/etc/namedb/named.conf" \
                   1430:                "${DEST_DIR}/etc/named.conf"
                   1431:
                   1432:        compare_dir "${op}" "${SRC_DIR}/etc/namedb" "${DEST_DIR}/etc/namedb" \
                   1433:                644 \
                   1434:                root.cache
                   1435: }
                   1436:
                   1437: #
                   1438: #      pam
                   1439: #
                   1440: additem pam "/etc/pam.d is populated"
                   1441: do_pam()
                   1442: {
                   1443:        [ -n "$1" ] || err 3 "USAGE: do_pam  fix|check"
                   1444:        op="$1"
                   1445:        failed=0
                   1446:
                   1447:        populate_dir "${op}" true "${SRC_DIR}/etc/pam.d" \
                   1448:                "${DEST_DIR}/etc/pam.d" 644 \
                   1449:                README cron display_manager ftpd gdm imap kde login other \
                   1450:                passwd pop3 ppp racoon rexecd rsh sshd su system telnetd \
                   1451:                xdm xserver
                   1452:
                   1453:        failed=$(( ${failed} + $? ))
                   1454:
                   1455:        return ${failed}
                   1456: }
                   1457:
                   1458: #
                   1459: #      periodic
                   1460: #
                   1461: additem periodic "/etc/{daily,weekly,monthly,security} being up to date"
                   1462: do_periodic()
                   1463: {
                   1464:        [ -n "$1" ] || err 3 "USAGE: do_periodic  fix|check"
                   1465:
                   1466:        compare_dir "$1" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \
                   1467:                daily weekly monthly security
                   1468: }
                   1469:
                   1470: #
                   1471: #      pf
                   1472: #
                   1473: additem pf "pf configuration being up to date"
                   1474: do_pf()
                   1475: {
                   1476:        [ -n "$1" ] || err 3 "USAGE: do_pf  fix|check"
                   1477:        op="$1"
                   1478:        failed=0
                   1479:
                   1480:        find_file_in_dirlist pf.os "pf.os" \
                   1481:            "${SRC_DIR}/dist/pf/etc" "${SRC_DIR}/etc" \
                   1482:            || return 1
                   1483:                        # ${dir} is set by find_file_in_dirlist()
                   1484:        populate_dir "${op}" true \
                   1485:            "${dir}" "${DEST_DIR}/etc" 644 \
                   1486:            pf.conf
                   1487:        failed=$(( ${failed} + $? ))
                   1488:
                   1489:        compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 pf.os
                   1490:        failed=$(( ${failed} + $? ))
                   1491:
                   1492:        return ${failed}
                   1493: }
                   1494:
                   1495: #
                   1496: #      pwd_mkdb
                   1497: #
                   1498: additem pwd_mkdb "passwd database version"
                   1499: do_pwd_mkdb()
                   1500: {
                   1501:        [ -n "$1" ] || err 3 "USAGE: do_pwd_mkdb  fix|check"
                   1502:        op="$1"
                   1503:        failed=0
                   1504:
                   1505:        # XXX Ideally, we should figure out the endianness of the
                   1506:        # target machine, and add "-E B"/"-E L" to the db(1) flags,
                   1507:        # and "-B"/"-L" to the pwd_mkdb(8) flags if the target is not
                   1508:        # the same as the host machine.  It probably doesn't matter,
                   1509:        # because we don't expect "postinstall fix pwd_mkdb" to be
                   1510:        # invoked during a cross build.
                   1511:
                   1512:        set -- $(${DB} -q -Sb -Ub -To -N hash "${DEST_DIR}/etc/pwd.db" \
                   1513:                'VERSION\0')
                   1514:        case "$2" in
                   1515:        '\001\000\000\000') return 0 ;; # version 1, little-endian
                   1516:        '\000\000\000\001') return 0 ;; # version 1, big-endian
                   1517:        esac
                   1518:
                   1519:        if [ "${op}" = "check" ]; then
                   1520:                msg "Update format of passwd database"
                   1521:                failed=1
                   1522:        elif ! ${PWD_MKDB} -V 1 -d "${DEST_DIR:-/}" \
                   1523:                        "${DEST_DIR}/etc/master.passwd";
                   1524:        then
                   1525:                msg "Can't update format of passwd database"
                   1526:                failed=1
                   1527:        else
                   1528:                msg "Updated format of passwd database"
                   1529:        fi
                   1530:
                   1531:        return ${failed}
                   1532: }
                   1533:
                   1534: #
                   1535: #      rc
                   1536: #
                   1537:
1.12      tsutsui  1538: # There is no info in src/distrib or /etc/mtree which rc* files
                   1539: # can be overwritten unconditionally on upgrade. See PR/54741.
                   1540: rc_644_files="
                   1541: rc
                   1542: rc.subr
                   1543: rc.shutdown
                   1544: "
                   1545:
1.1       christos 1546: rc_obsolete_vars="
                   1547: amd amd_master
                   1548: btcontrol btcontrol_devices
                   1549: critical_filesystems critical_filesystems_beforenet
                   1550: mountcritlocal mountcritremote
                   1551: network ip6forwarding
                   1552: network nfsiod_flags
                   1553: sdpd sdpd_control
                   1554: sdpd sdpd_groupname
                   1555: sdpd sdpd_username
                   1556: sysctl defcorename
                   1557: "
                   1558:
                   1559: update_rc()
                   1560: {
                   1561:        local op=$1
                   1562:        local dir=$2
                   1563:        local name=$3
                   1564:        local bindir=$4
                   1565:        local rcdir=$5
                   1566:
                   1567:        if [ ! -x "${DEST_DIR}/${bindir}/${name}" ]; then
                   1568:                return 0
                   1569:        fi
                   1570:
                   1571:        if ! find_file_in_dirlist "${name}" "${name}" \
                   1572:            "${rcdir}" "${SRC_DIR}/etc/rc.d"; then
                   1573:                return 1
                   1574:        fi
                   1575:        populate_dir "${op}" false "${dir}" "${DEST_DIR}/etc/rc.d" 555 "${name}"
                   1576:        return $?
                   1577: }
                   1578:
                   1579: # select non-obsolete files in a sets file
                   1580: # $1: directory pattern
                   1581: # $2: file pattern
                   1582: # $3: filename
                   1583: select_set_files()
                   1584: {
                   1585:        local qdir="$(echo $1 | ${SED} -e s@/@\\\\/@g -e s/\\./\\\\./g)"
                   1586:        ${SED} -n -e /obsolete/d \
                   1587:            -e "/^\.${qdir}/s@^.$2[[:space:]].*@\1@p" $3
                   1588: }
                   1589:
1.4       christos 1590: # select obsolete files in a sets file
                   1591: # $1: directory pattern
                   1592: # $2: file pattern
1.10      christos 1593: # $3: setname
1.4       christos 1594: select_obsolete_files()
                   1595: {
1.10      christos 1596:        if $SOURCEMODE; then
                   1597:                ${SED} -n -e "/obsolete/s@\.$1$2[[:space:]].*@\1@p" \
                   1598:                    ${SRC_DIR}/distrib/sets/lists/$3/mi
1.11      christos 1599:                return
                   1600:        fi
                   1601:
                   1602:        # On upgrade builds we don't extract the "etc" set so we
                   1603:        # try to use the source set instead. See PR/54730 for
                   1604:        # ways to better handle this.
                   1605:
                   1606:        local obsolete_dir
                   1607:
                   1608:        if [ $3 = "etc" ] ;then
                   1609:                obsolete_dir=${SRC_DIR}/var/db/obsolete
1.10      christos 1610:        else
1.11      christos 1611:                obsolete_dir=${DEST_DIR}/var/db/obsolete
1.10      christos 1612:        fi
1.11      christos 1613:        ${SED} -n -e "s@\.$1$2\$@\1@p" "${obsolete_dir}/$3"
1.4       christos 1614: }
                   1615:
1.1       christos 1616: getetcsets()
                   1617: {
                   1618:        if $SOURCEMODE; then
                   1619:                echo "${SRC_DIR}/distrib/sets/lists/etc/mi"
                   1620:        else
                   1621:                echo "${SRC_DIR}/etc/mtree/set.etc"
                   1622:        fi
                   1623: }
                   1624:
                   1625: additem rc "/etc/rc* and /etc/rc.d/ being up to date"
                   1626: do_rc()
                   1627: {
                   1628:        [ -n "$1" ] || err 3 "USAGE: do_rc  fix|check"
                   1629:        local op="$1"
                   1630:        local failed=0
                   1631:        local generated_scripts=""
                   1632:        local etcsets=$(getetcsets)
                   1633:        if [ "${MKX11}" != "no" ]; then
                   1634:                generated_scripts="${generated_scripts} xdm xfs"
                   1635:        fi
                   1636:
                   1637:        # Directories of external programs that have rc files (in bsd)
1.26      christos 1638:        local rc_external_files="blocklist nsd unbound"
1.1       christos 1639:
                   1640:        # rc* files in /etc/
1.12      tsutsui  1641:        # XXX: at least rc.conf and rc.local shouldn't be updated. PR/54741
                   1642:        #local rc_644_files="$(select_set_files /etc/rc \
                   1643:        #    "/etc/\(rc[^[:space:]/]*\)" ${etcsets})"
1.1       christos 1644:
                   1645:        # no-obsolete rc files in /etc/rc.d
                   1646:        local rc_555_files="$(select_set_files /etc/rc.d/ \
                   1647:            "/etc/rc\.d/\([^[:space:]]*\)" ${etcsets} | \
                   1648:            exclude ${rc_external_files})"
                   1649:
                   1650:        # obsolete rc file in /etc/rc.d
1.4       christos 1651:        local rc_obsolete_files="$(select_obsolete_files /etc/rc.d/ \
1.10      christos 1652:            "\([^[:space:]]*\)" etc)"
1.1       christos 1653:
                   1654:        compare_dir "${op}" "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 \
                   1655:                ${rc_644_files}
                   1656:        failed=$(( ${failed} + $? ))
                   1657:
                   1658:        local extra_scripts
                   1659:        if ! $SOURCEMODE; then
                   1660:                extra_scripts="${generated_scripts}"
                   1661:        else
                   1662:                extra_scripts=""
                   1663:        fi
                   1664:
                   1665:        compare_dir "${op}" "${SRC_DIR}/etc/rc.d" "${DEST_DIR}/etc/rc.d" 555 \
                   1666:                ${rc_555_files} \
                   1667:                ${extra_scripts}
                   1668:        failed=$(( ${failed} + $? ))
                   1669:
                   1670:        for i in ${rc_external_files}; do
1.28      riastrad 1671:            local rc_file
1.1       christos 1672:            case $i in
                   1673:            *d) rc_file=${i};;
                   1674:            *)  rc_file=${i}d;;
                   1675:            esac
1.28      riastrad 1676:
1.1       christos 1677:            update_rc "${op}" "${dir}" ${rc_file} /sbin \
                   1678:                "${SRC_DIR}/external/bsd/$i/etc/rc.d"
                   1679:            failed=$(( ${failed} + $? ))
                   1680:        done
                   1681:
                   1682:        if $SOURCEMODE && [ -n "${generated_scripts}" ]; then
                   1683:                # generate scripts
                   1684:                mkdir "${SCRATCHDIR}/rc"
                   1685:                for f in ${generated_scripts}; do
                   1686:                        ${SED} -e "s,@X11ROOTDIR@,${X11ROOTDIR},g" \
                   1687:                            < "${SRC_DIR}/etc/rc.d/${f}.in" \
                   1688:                            > "${SCRATCHDIR}/rc/${f}"
                   1689:                done
                   1690:                compare_dir "${op}" "${SCRATCHDIR}/rc" \
                   1691:                    "${DEST_DIR}/etc/rc.d" 555 \
                   1692:                    ${generated_scripts}
                   1693:                failed=$(( ${failed} + $? ))
                   1694:        fi
                   1695:
                   1696:                # check for obsolete rc.d files
                   1697:        for f in ${rc_obsolete_files}; do
                   1698:                local fd="/etc/rc.d/${f}"
                   1699:                [ -e "${DEST_DIR}${fd}" ] && echo "${fd}"
                   1700:        done | obsolete_paths "${op}"
                   1701:        failed=$(( ${failed} + $? ))
                   1702:
                   1703:                # check for obsolete rc.conf(5) variables
                   1704:        set -- ${rc_obsolete_vars}
                   1705:        while [ $# -gt 1 ]; do
                   1706:                if rcconf_is_set "${op}" "$1" "$2" 1; then
                   1707:                        failed=1
                   1708:                fi
                   1709:                shift 2
                   1710:        done
                   1711:
                   1712:        return ${failed}
                   1713: }
                   1714:
                   1715: #
                   1716: #      sendmail
                   1717: #
                   1718: adddisableditem sendmail "remove obsolete sendmail configuration files and scripts"
                   1719: do_sendmail()
                   1720: {
                   1721:        [ -n "$1" ] || err 3 "USAGE: do_sendmail  fix|check"
                   1722:        op="$1"
                   1723:        failed=0
                   1724:
                   1725:        # Don't complain if the "sendmail" package is installed because the
                   1726:        # files might still be in use.
                   1727:        if /usr/sbin/pkg_info -qe sendmail >/dev/null 2>&1; then
                   1728:                return 0
                   1729:        fi
                   1730:
                   1731:        for f in /etc/mail/helpfile /etc/mail/local-host-names \
                   1732:            /etc/mail/sendmail.cf /etc/mail/submit.cf /etc/rc.d/sendmail \
                   1733:            /etc/rc.d/smmsp /usr/share/misc/sendmail.hf \
                   1734:            $( ( find "${DEST_DIR}/usr/share/sendmail" -type f ; \
                   1735:                 find "${DEST_DIR}/usr/share/sendmail" -type d \
                   1736:               ) | unprefix "${DEST_DIR}" ) \
                   1737:            /var/log/sendmail.st \
                   1738:            /var/spool/clientmqueue \
                   1739:            /var/spool/mqueue
                   1740:        do
                   1741:                [ -e "${DEST_DIR}${f}" ] && echo "${f}"
                   1742:        done | obsolete_paths "${op}"
                   1743:        failed=$(( ${failed} + $? ))
                   1744:
                   1745:        return ${failed}
                   1746: }
                   1747:
                   1748: #
                   1749: #      mailerconf
                   1750: #
                   1751: adddisableditem mailerconf "update /etc/mailer.conf after sendmail removal"
                   1752: do_mailerconf()
                   1753: {
                   1754:        [ -n "$1" ] || err 3 "USAGE: do_mailterconf  fix|check"
                   1755:        op="$1"
                   1756:
                   1757:        failed=0
                   1758:        mta_path="$(${AWK} '/^sendmail[ \t]/{print$2}' \
                   1759:                "${DEST_DIR}/etc/mailer.conf")"
                   1760:        old_sendmail_path="/usr/libexec/sendmail/sendmail"
                   1761:        if [ "${mta_path}" = "${old_sendmail_path}" ]; then
                   1762:            if [ "$op" = check ]; then
                   1763:                msg "mailer.conf points to obsolete ${old_sendmail_path}"
                   1764:                failed=1;
                   1765:            else
                   1766:                populate_dir "${op}" false \
                   1767:                "${SRC_DIR}/etc" "${DEST_DIR}/etc" 644 mailer.conf
                   1768:                failed=$?
                   1769:            fi
                   1770:        fi
                   1771:
                   1772:        return ${failed}
                   1773: }
                   1774:
                   1775: #
                   1776: #      ssh
                   1777: #
                   1778: additem ssh "ssh configuration update"
                   1779: do_ssh()
                   1780: {
                   1781:        [ -n "$1" ] || err 3 "USAGE: do_ssh  fix|check"
                   1782:        op="$1"
                   1783:
                   1784:        failed=0
                   1785:        _etcssh="${DEST_DIR}/etc/ssh"
                   1786:        if ! check_dir "${op}" "${_etcssh}" 755; then
                   1787:                failed=1
                   1788:        fi
                   1789:
                   1790:        if [ ${failed} -eq 0 ]; then
                   1791:                for f in \
                   1792:                            ssh_known_hosts ssh_known_hosts2 \
                   1793:                            ssh_host_dsa_key ssh_host_dsa_key.pub \
                   1794:                            ssh_host_rsa_key ssh_host_rsa_key.pub \
                   1795:                            ssh_host_key ssh_host_key.pub \
                   1796:                    ; do
                   1797:                        if ! move_file "${op}" \
                   1798:                            "${DEST_DIR}/etc/${f}" "${_etcssh}/${f}" ; then
                   1799:                                failed=1
                   1800:                        fi
                   1801:                done
                   1802:                for f in sshd.conf ssh.conf ; do
                   1803:                                # /etc/ssh/ssh{,d}.conf -> ssh{,d}_config
                   1804:                                #
                   1805:                        if ! move_file "${op}" \
                   1806:                            "${_etcssh}/${f}" "${_etcssh}/${f%.conf}_config" ;
                   1807:                        then
                   1808:                                failed=1
                   1809:                        fi
                   1810:                                # /etc/ssh{,d}.conf -> /etc/ssh/ssh{,d}_config
                   1811:                                #
                   1812:                        if ! move_file "${op}" \
                   1813:                            "${DEST_DIR}/etc/${f}" \
                   1814:                            "${_etcssh}/${f%.conf}_config" ;
                   1815:                        then
                   1816:                                failed=1
                   1817:                        fi
                   1818:                done
                   1819:        fi
                   1820:
                   1821:        sshdconf=""
                   1822:        for f in \
                   1823:            "${_etcssh}/sshd_config" \
                   1824:            "${_etcssh}/sshd.conf" \
                   1825:            "${DEST_DIR}/etc/sshd.conf" ; do
                   1826:                if [ -f "${f}" ]; then
                   1827:                        sshdconf="${f}"
                   1828:                        break
                   1829:                fi
                   1830:        done
                   1831:        if [ -n "${sshdconf}" ]; then
                   1832:                modify_file "${op}" "${sshdconf}" "${SCRATCHDIR}/sshdconf" '
                   1833:                        /^[^#$]/ {
                   1834:                                kw = tolower($1)
                   1835:                                if (kw == "hostkey" &&
                   1836:                                    $2 ~ /^\/etc\/+ssh_host(_[dr]sa)?_key$/ ) {
                   1837:                                        sub(/\/etc\/+/, "/etc/ssh/")
                   1838:                                }
                   1839:                                if (kw == "rhostsauthentication" ||
                   1840:                                    kw == "verifyreversemapping" ||
                   1841:                                    kw == "reversemappingcheck") {
                   1842:                                        sub(/^/, "# DEPRECATED:\t")
                   1843:                                }
                   1844:                        }
                   1845:                        { print }
                   1846:                '
                   1847:                failed=$(( ${failed} + $? ))
                   1848:        fi
                   1849:
                   1850:        if ! find_file_in_dirlist moduli "moduli" \
                   1851:            "${SRC_DIR}/crypto/external/bsd/openssh/dist" "${SRC_DIR}/etc" ; then
                   1852:                failed=1
                   1853:                        # ${dir} is set by find_file_in_dirlist()
                   1854:        elif ! compare_dir "${op}" "${dir}" "${DEST_DIR}/etc" 444 moduli; then
                   1855:                failed=1
                   1856:        fi
                   1857:
                   1858:        if ! check_dir "${op}" "${DEST_DIR}/var/chroot/sshd" 755 ; then
                   1859:                failed=1
                   1860:        fi
                   1861:
                   1862:        if rcconf_is_set "${op}" sshd sshd_conf_dir 1; then
                   1863:                failed=1
                   1864:        fi
                   1865:
                   1866:        return ${failed}
                   1867: }
                   1868:
                   1869: #
                   1870: #      wscons
                   1871: #
                   1872: additem wscons "wscons configuration file update"
                   1873: do_wscons()
                   1874: {
                   1875:        [ -n "$1" ] || err 3 "USAGE: do_wscons  fix|check"
                   1876:        op="$1"
                   1877:
                   1878:        [ -f "${DEST_DIR}/etc/wscons.conf" ] || return 0
                   1879:
                   1880:        failed=0
                   1881:        notfixed=""
                   1882:        if [ "${op}" = "fix" ]; then
                   1883:                notfixed="${NOT_FIXED}"
                   1884:        fi
                   1885:        while read _type _arg1 _rest; do
                   1886:                if [ "${_type}" = "mux" -a "${_arg1}" = "1" ]; then
                   1887:                        msg \
                   1888:     "Obsolete wscons.conf(5) entry \""${_type} ${_arg1}"\" found.${notfixed}"
                   1889:                        failed=1
                   1890:                fi
                   1891:        done < "${DEST_DIR}/etc/wscons.conf"
                   1892:
                   1893:        return ${failed}
                   1894: }
                   1895:
                   1896: #
                   1897: #      X11
                   1898: #
                   1899: additem x11 "x11 configuration update"
                   1900: do_x11()
                   1901: {
                   1902:        [ -n "$1" ] || err 3 "USAGE: do_x11  fix|check"
                   1903:        op="$1"
                   1904:
                   1905:        failed=0
                   1906:        _etcx11="${DEST_DIR}/etc/X11"
                   1907:        if [ ! -d "${_etcx11}" ]; then
                   1908:                msg "${_etcx11} is not a directory; skipping check"
                   1909:                return 0
                   1910:        fi
                   1911:        if [ -d "${DEST_DIR}/usr/X11R6/." ]
                   1912:        then
                   1913:                _libx11="${DEST_DIR}/usr/X11R6/lib/X11"
                   1914:                if [ ! -d "${_libx11}" ]; then
                   1915:                        msg "${_libx11} is not a directory; skipping check"
                   1916:                        return 0
                   1917:                fi
                   1918:        fi
                   1919:
                   1920:        _notfixed=""
                   1921:        if [ "${op}" = "fix" ]; then
                   1922:                _notfixed="${NOT_FIXED}"
                   1923:        fi
                   1924:
                   1925:        for d in \
                   1926:                    fs lbxproxy proxymngr rstart twm xdm xinit xserver xsm \
                   1927:            ; do
                   1928:                sd="${_libx11}/${d}"
                   1929:                ld="/etc/X11/${d}"
                   1930:                td="${DEST_DIR}${ld}"
                   1931:                if [ -h "${sd}" ]; then
                   1932:                        continue
                   1933:                elif [ -d "${sd}" ]; then
                   1934:                        tdfiles="$(find "${td}" \! -type d)"
                   1935:                        if [ -n "${tdfiles}" ]; then
                   1936:                                msg "${sd} exists yet ${td} already" \
                   1937:                                    "contains files${_notfixed}"
                   1938:                        else
                   1939:                                msg "Migrate ${sd} to ${td}${_notfixed}"
                   1940:                        fi
                   1941:                        failed=1
                   1942:                elif [ -e "${sd}" ]; then
                   1943:                        msg "Unexpected file ${sd}${_notfixed}"
                   1944:                        continue
                   1945:                else
                   1946:                        continue
                   1947:                fi
                   1948:        done
                   1949:
                   1950:        # check if xdm resources have been updated
                   1951:        if [ -r ${_etcx11}/xdm/Xresources ] && \
                   1952:            ! ${GREP} 'inpColor:' ${_etcx11}/xdm/Xresources > /dev/null; then
                   1953:                msg "Update ${_etcx11}/xdm/Xresources${_notfixed}"
                   1954:                failed=1
                   1955:        fi
                   1956:
                   1957:        return ${failed}
                   1958: }
                   1959:
                   1960: #
                   1961: #      xkb
                   1962: #
                   1963: # /usr/X11R7/lib/X11/xkb/symbols/pc used to be a directory, but changed
                   1964: # to a file on 2009-06-12.  Fixing this requires removing the directory
                   1965: # (which we can do) and re-extracting the xbase set (which we can't do),
                   1966: # or at least adding that one file (which we may be able to do if X11SRCDIR
                   1967: # is available).
                   1968: #
                   1969: additem xkb "clean up for xkbdata to xkeyboard-config upgrade"
                   1970: do_xkb()
                   1971: {
                   1972:        [ -n "$1" ] || err 3 "USAGE: do_xkb  fix|check"
                   1973:        op="$1"
                   1974:        failed=0
                   1975:
                   1976:        pcpath="/usr/X11R7/lib/X11/xkb/symbols/pc"
                   1977:        pcsrcdir="${X11SRCDIR}/external/mit/xkeyboard-config/dist/symbols"
                   1978:
                   1979:        filemsg="\
                   1980: ${pcpath} was a directory, should be a file.
                   1981:     To fix, extract the xbase set again."
                   1982:
                   1983:        _notfixed=""
                   1984:        if [ "${op}" = "fix" ]; then
                   1985:                _notfixed="${NOT_FIXED}"
                   1986:        fi
                   1987:
                   1988:        if [ ! -d "${DEST_DIR}${pcpath}" ]; then
                   1989:                return 0
                   1990:        fi
                   1991:
                   1992:        # Delete obsolete files in the directory, and the directory
                   1993:        # itself.  If the directory contains unexpected extra files
                   1994:        # then it will not be deleted.
                   1995:        ( [ -f "${DEST_DIR}"/var/db/obsolete/xbase ] \
                   1996:            &&  ${SORT} -ru "${DEST_DIR}"/var/db/obsolete/xbase \
                   1997:            | ${GREP} -E "^\\.?${pcpath}/" ;
                   1998:            echo "${pcpath}" ) \
                   1999:        | obsolete_paths "${op}"
                   2000:        failed=$(( ${failed} + $? ))
                   2001:
                   2002:        # If the directory was removed above, then try to replace it with
                   2003:        # a file.
                   2004:        if [ -d "${DEST_DIR}${pcpath}" ]; then
                   2005:                msg "${filemsg}${_notfixed}"
                   2006:                failed=$(( ${failed} + 1 ))
                   2007:        else
                   2008:                if ! find_file_in_dirlist pc "${pcpath}" \
                   2009:                        "${pcsrcdir}" "${SRC_DIR}${pcpath%/*}"
                   2010:                then
                   2011:                        msg "${filemsg}${_notfixed}"
                   2012:                        failed=$(( ${failed} + 1 ))
                   2013:                else
                   2014:                        # ${dir} is set by find_file_in_dirlist()
                   2015:                        populate_dir "${op}" true \
                   2016:                                "${dir}" "${DEST_DIR}${pcpath%/*}" 444 \
                   2017:                                pc
                   2018:                        failed=$(( ${failed} + $? ))
                   2019:                fi
                   2020:        fi
                   2021:
                   2022:        return $failed
                   2023: }
                   2024:
                   2025: #
                   2026: #      uid
                   2027: #
                   2028: additem uid "required users in /etc/master.passwd"
                   2029: do_uid()
                   2030: {
                   2031:        [ -n "$1" ] || err 3 "USAGE: do_uid  fix|check"
                   2032:
                   2033:        check_ids "$1" users "${DEST_DIR}/etc/master.passwd" \
                   2034:            "${SRC_DIR}/etc/master.passwd" 12 \
                   2035:            postfix SKIP named ntpd sshd SKIP _pflogd _rwhod SKIP _proxy \
                   2036:            _timedc _sdpd _httpd _mdnsd _tests _tcpdump _tss SKIP _rtadvd \
1.17      roy      2037:            SKIP _unbound _nsd SKIP _dhcpcd
1.1       christos 2038: }
                   2039:
                   2040:
                   2041: #
                   2042: #      varrwho
                   2043: #
                   2044: additem varrwho "required ownership of files in /var/rwho"
                   2045: do_varrwho()
                   2046: {
                   2047:        [ -n "$1" ] || err 3 "USAGE: do_varrwho  fix|check"
                   2048:
                   2049:        contents_owner "$1" "${DEST_DIR}/var/rwho" _rwhod _rwhod
                   2050: }
                   2051:
                   2052:
                   2053: #
                   2054: #      tcpdumpchroot
                   2055: #
                   2056: additem tcpdumpchroot "remove /var/chroot/tcpdump/etc/protocols"
                   2057: do_tcpdumpchroot()
                   2058: {
                   2059:        [ -n "$1" ] || err 3 "USAGE: do_tcpdumpchroot  fix|check"
                   2060:
                   2061:        failed=0;
                   2062:        if [ -r "${DEST_DIR}/var/chroot/tcpdump/etc/protocols" ]; then
                   2063:                if [ "$1" = "fix" ]; then
                   2064:                        rm "${DEST_DIR}/var/chroot/tcpdump/etc/protocols"
                   2065:                        failed=$(( ${failed} + $? ))
                   2066:                        rmdir "${DEST_DIR}/var/chroot/tcpdump/etc"
                   2067:                        failed=$(( ${failed} + $? ))
                   2068:                else
                   2069:                        failed=1
                   2070:                fi
                   2071:        fi
                   2072:        return ${failed}
                   2073: }
                   2074:
                   2075:
                   2076: #
                   2077: #      atf
                   2078: #
                   2079: additem atf "install missing atf configuration files and validate them"
                   2080: do_atf()
                   2081: {
                   2082:        [ -n "$1" ] || err 3 "USAGE: do_atf  fix|check"
                   2083:        op="$1"
                   2084:        failed=0
                   2085:
                   2086:        # Ensure atf configuration files are in place.
                   2087:        if find_file_in_dirlist NetBSD.conf "NetBSD.conf" \
                   2088:            "${SRC_DIR}/external/bsd/atf/etc/atf" \
                   2089:            "${SRC_DIR}/etc/atf"; then
                   2090:                        # ${dir} is set by find_file_in_dirlist()
                   2091:                populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \
                   2092:                    NetBSD.conf common.conf || failed=1
                   2093:        else
                   2094:                failed=1
                   2095:        fi
                   2096:        if find_file_in_dirlist atf-run.hooks "atf-run.hooks" \
                   2097:            "${SRC_DIR}/external/bsd/atf/dist/tools/sample" \
                   2098:            "${SRC_DIR}/etc/atf"; then
                   2099:                        # ${dir} is set by find_file_in_dirlist()
                   2100:                populate_dir "${op}" true "${dir}" "${DEST_DIR}/etc/atf" 644 \
                   2101:                    atf-run.hooks || failed=1
                   2102:        else
                   2103:                failed=1
                   2104:        fi
                   2105:
                   2106:        # Validate the _atf to _tests user/group renaming.
                   2107:        if [ -f "${DEST_DIR}/etc/atf/common.conf" ]; then
                   2108:                handle_atf_user "${op}" || failed=1
                   2109:        else
                   2110:                failed=1
                   2111:        fi
                   2112:
                   2113:        return ${failed}
                   2114: }
                   2115:
                   2116: handle_atf_user()
                   2117: {
                   2118:        local op="$1"
                   2119:        local failed=0
                   2120:
                   2121:        local conf="${DEST_DIR}/etc/atf/common.conf"
                   2122:        if grep '[^#]*unprivileged-user[ \t]*=.*_atf' "${conf}" >/dev/null
                   2123:        then
                   2124:                if [ "$1" = "fix" ]; then
                   2125:                        ${SED} -e \
                   2126:                            "/[^#]*unprivileged-user[\ t]*=/s/_atf/_tests/" \
                   2127:                            "${conf}" >"${conf}.new"
                   2128:                        failed=$(( ${failed} + $? ))
                   2129:                        mv "${conf}.new" "${conf}"
                   2130:                        failed=$(( ${failed} + $? ))
                   2131:                        msg "Set unprivileged-user=_tests in ${conf}"
                   2132:                else
                   2133:                        msg "unprivileged-user=_atf in ${conf} should be" \
                   2134:                            "unprivileged-user=_tests"
                   2135:                        failed=1
                   2136:                fi
                   2137:        fi
                   2138:
                   2139:        return ${failed}
                   2140: }
                   2141:
                   2142: #
                   2143: #      catpages
                   2144: #
                   2145: obsolete_catpages()
                   2146: {
                   2147:        basedir="$2"
                   2148:        section="$3"
                   2149:        mandir="${basedir}/man${section}"
                   2150:        catdir="${basedir}/cat${section}"
                   2151:        test -d "$mandir" || return 0
                   2152:        test -d "$catdir" || return 0
                   2153:        (cd "$mandir" && find . -type f) | {
                   2154:        failed=0
                   2155:        while read manpage; do
                   2156:                manpage="${manpage#./}"
                   2157:                case "$manpage" in
                   2158:                *.Z)
                   2159:                        catname="$catdir/${manpage%.*.Z}.0"
                   2160:                        ;;
                   2161:                *.gz)
                   2162:                        catname="$catdir/${manpage%.*.gz}.0"
                   2163:                        ;;
                   2164:                *)
                   2165:                        catname="$catdir/${manpage%.*}.0"
                   2166:                        ;;
                   2167:                esac
                   2168:                test -e "$catname" -a "$catname" -ot "$mandir/$manpage" || continue
                   2169:                if [ "$1" = "fix" ]; then
                   2170:                        rm "$catname"
                   2171:                        failed=$(( ${failed} + $? ))
                   2172:                        msg "Removed obsolete cat page $catname"
                   2173:                else
                   2174:                        msg "Obsolete cat page $catname"
                   2175:                        failed=1
                   2176:                fi
                   2177:        done
                   2178:        exit $failed
                   2179:        }
                   2180: }
                   2181:
                   2182: additem catpages "remove outdated cat pages"
                   2183: do_catpages()
                   2184: {
                   2185:        failed=0
                   2186:        for manbase in /usr/share/man /usr/X11R6/man /usr/X11R7/man; do
                   2187:                for sec in 1 2 3 4 5 6 7 8 9; do
                   2188:                        obsolete_catpages "$1" "${DEST_DIR}${manbase}" "${sec}"
                   2189:                        failed=$(( ${failed} + $? ))
                   2190:                        if [ "$1" = "fix" ]; then
                   2191:                                rmdir "${DEST_DIR}${manbase}/cat${sec}"/* \
                   2192:                                        2>/dev/null
                   2193:                                rmdir "${DEST_DIR}${manbase}/cat${sec}" \
                   2194:                                        2>/dev/null
                   2195:                        fi
                   2196:                done
                   2197:        done
                   2198:        return $failed
                   2199: }
                   2200:
                   2201: #
                   2202: #      man.conf
                   2203: #
                   2204: additem manconf "check for a mandoc usage in /etc/man.conf"
                   2205: do_manconf()
                   2206: {
                   2207:        [ -n "$1" ] || err 3 "USAGE: do_manconf  fix|check"
                   2208:        op="$1"
                   2209:        failed=0
                   2210:
                   2211:        [ -f "${DEST_DIR}/etc/man.conf" ] || return 0
                   2212:        if ${GREP} -w "mandoc" "${DEST_DIR}/etc/man.conf" >/dev/null 2>&1;
                   2213:        then
                   2214:                failed=0;
                   2215:        else
                   2216:                failed=1
                   2217:                notfixed=""
                   2218:                if [ "${op}" = "fix" ]; then
                   2219:                        notfixed="${NOT_FIXED}"
                   2220:                fi
                   2221:                msg "The file /etc/man.conf has not been adapted to mandoc usage; you"
                   2222:                msg "probably want to copy a new version over. ${notfixed}"
                   2223:        fi
                   2224:
                   2225:        return ${failed}
                   2226: }
                   2227:
                   2228:
                   2229: #
                   2230: #      ptyfsoldnodes
                   2231: #
                   2232: additem ptyfsoldnodes "remove legacy device nodes when using ptyfs"
                   2233: do_ptyfsoldnodes()
                   2234: {
                   2235:        [ -n "$1" ] || err 3 "USAGE: do_ptyfsoldnodes  fix|check"
                   2236:        _ptyfs_op="$1"
                   2237:
                   2238:        # Check whether ptyfs is in use
                   2239:        failed=0;
                   2240:        if ! ${GREP} -E "^ptyfs" "${DEST_DIR}/etc/fstab" > /dev/null; then
                   2241:                msg "ptyfs is not in use"
                   2242:                return 0
                   2243:        fi
                   2244:
                   2245:        if [ ! -e "${DEST_DIR}/dev/pts" ]; then
                   2246:                msg "ptyfs is not properly configured: missing /dev/pts"
                   2247:                return 1
                   2248:        fi
                   2249:
                   2250:        # Find the device major numbers for the pty master and slave
                   2251:        # devices, by parsing the output from "MAKEDEV -s pty0".
                   2252:        #
                   2253:        # Output from MAKEDEV looks like this:
                   2254:        # ./ttyp0 type=char device=netbsd,5,0 mode=666 gid=0 uid=0
                   2255:        # ./ptyp0 type=char device=netbsd,6,0 mode=666 gid=0 uid=0
                   2256:        #
                   2257:        # Output from awk, used in the eval statement, looks like this:
                   2258:        # maj_ptym=6; maj_ptys=5;
                   2259:        #
                   2260:        find_makedev
                   2261:        eval "$(
                   2262:            ${HOST_SH} "${MAKEDEV_DIR}/MAKEDEV" -s pty0 2>/dev/null \
                   2263:            | ${AWK} '\
                   2264:            BEGIN { before_re = ".*device=[a-zA-Z]*,"; after_re = ",.*"; }
                   2265:            /ptyp0/ { maj_ptym = gensub(before_re, "", 1, $0);
                   2266:                      maj_ptym = gensub(after_re, "", 1, maj_ptym); }
                   2267:            /ttyp0/ { maj_ptys = gensub(before_re, "", 1, $0);
                   2268:                      maj_ptys = gensub(after_re, "", 1, maj_ptys); }
                   2269:            END { print "maj_ptym=" maj_ptym "; maj_ptys=" maj_ptys ";"; }
                   2270:            '
                   2271:            )"
                   2272:        #msg "Major numbers are maj_ptym=${maj_ptym} maj_ptys=${maj_ptys}"
                   2273:        if [ -z "$maj_ptym" ] || [ -z "$maj_ptys" ]; then
                   2274:                msg "Cannot find device major numbers for pty master and slave"
                   2275:                return 1
                   2276:        fi
                   2277:
                   2278:        # look for /dev/[pt]ty[p-zP-T][0-9a-zA-Z], and check that they
                   2279:        # have the expected device major numbers.  ttyv* is typically not a
                   2280:        # pty device, but we check it anyway.
                   2281:        #
                   2282:        # The "for d1" loop is intended to avoid overflowing ARG_MAX;
                   2283:        # otherwise we could have used a single glob pattern.
                   2284:        #
                   2285:        # If there are no files that match a particular pattern,
                   2286:        # then stat prints something like:
                   2287:        #    stat: /dev/[pt]tyx?: lstat: No such file or directory
                   2288:        # and we ignore it.  XXX: We also ignore other error messages.
                   2289:        #
                   2290:        _ptyfs_tmp="$(mktemp /tmp/postinstall.ptyfs.XXXXXXXX)"
                   2291:        for d1 in p q r s t u v w x y z P Q R S T; do
                   2292:                ${STAT} -f "%Hr %N" "${DEST_DIR}/dev/"[pt]ty${d1}? 2>&1
                   2293:        done \
                   2294:        | while read -r major node ; do
                   2295:                case "$major" in
                   2296:                ${maj_ptym}|${maj_ptys}) echo "$node" ;;
                   2297:                esac
                   2298:        done >"${_ptyfs_tmp}"
                   2299:
                   2300:        _desc="legacy device node"
                   2301:        while read node; do
                   2302:                if [ "${_ptyfs_op}" = "check" ]; then
                   2303:                        msg "Remove ${_desc} ${node}"
                   2304:                        failed=1
                   2305:                else # "fix"
                   2306:                        if rm "${node}"; then
                   2307:                                msg "Removed ${_desc} ${node}"
                   2308:                        else
                   2309:                                warn "Failed to remove ${_desc} ${node}"
                   2310:                                failed=1
                   2311:                        fi
                   2312:                fi
                   2313:        done < "${_ptyfs_tmp}"
                   2314:        rm "${_ptyfs_tmp}"
                   2315:
                   2316:        return ${failed}
                   2317: }
                   2318:
                   2319:
                   2320: #
                   2321: #      varshm
                   2322: #
                   2323: additem varshm "check for a tmpfs mounted on /var/shm"
                   2324: do_varshm()
                   2325: {
                   2326:        [ -n "$1" ] || err 3 "USAGE: do_varshm  fix|check"
                   2327:        op="$1"
                   2328:        failed=0
                   2329:
                   2330:        [ -f "${DEST_DIR}/etc/fstab" ] || return 0
                   2331:        if ${GREP} -E "^var_shm_symlink" "${DEST_DIR}/etc/rc.conf" >/dev/null 2>&1;
                   2332:        then
                   2333:                failed=0;
                   2334:        elif ${GREP} -w "/var/shm" "${DEST_DIR}/etc/fstab" >/dev/null 2>&1;
                   2335:        then
                   2336:                failed=0;
                   2337:        else
                   2338:                if [ "${op}" = "check" ]; then
                   2339:                        failed=1
                   2340:                        msg "No /var/shm mount found in ${DEST_DIR}/etc/fstab"
                   2341:                elif [ "${op}" = "fix" ]; then
                   2342:                        printf '\ntmpfs\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n' \
                   2343:                                >> "${DEST_DIR}/etc/fstab"
                   2344:                        msg "Added tmpfs with 25% ram limit as /var/shm"
                   2345:
                   2346:                fi
                   2347:        fi
                   2348:
                   2349:        return ${failed}
                   2350: }
                   2351:
                   2352: #
                   2353: #      obsolete_stand
                   2354: #
1.21      christos 2355: obsolete_stand_internal()
1.1       christos 2356: {
1.21      christos 2357:        local prefix="$1"
                   2358:        shift
                   2359:        [ -n "$1" ] || err 3 "USAGE: do_obsolete_stand  fix|check"
                   2360:        local op="$1"
                   2361:        local failed=0
1.1       christos 2362:
                   2363:        for dir in \
1.21      christos 2364:            ${prefix}/stand/${MACHINE} \
                   2365:            ${prefix}/stand/${MACHINE}-4xx \
                   2366:            ${prefix}/stand/${MACHINE}-booke \
                   2367:            ${prefix}/stand/${MACHINE}-xen \
                   2368:            ${prefix}/stand/${MACHINE}pae-xen
1.1       christos 2369:        do
                   2370:                [ -d "${DESTDIR}${dir}" ] && obsolete_stand "${dir}"
                   2371:        done | obsolete_paths "${op}"
                   2372:        failed=$(( ${failed} + $? ))
                   2373:
                   2374:        return ${failed}
                   2375: }
                   2376:
1.21      christos 2377: adddisableditem obsolete_stand "remove obsolete files from /stand"
                   2378: do_obsolete_stand()
                   2379: {
                   2380:        obsolete_stand_internal "" "$@"
                   2381:        return $?
                   2382: }
                   2383:
                   2384: adddisableditem obsolete_stand_debug "remove obsolete files from /usr/libdata/debug/stand"
                   2385: do_obsolete_stand_debug()
                   2386: {
                   2387:        obsolete_stand_internal "/usr/libdata/debug" "$@"
                   2388:        return $?
                   2389: }
                   2390:
1.2       christos 2391: listarchsubdirs() {
1.1       christos 2392:        if ! $SOURCEMODE; then
                   2393:                echo "@ARCHSUBDIRS@"
1.2       christos 2394:        else
                   2395:                ${SED} -n -e '/ARCHDIR_SUBDIR/s/[[:space:]]//gp' \
1.28      riastrad 2396:                    ${SRC_DIR}/compat/archdirs.mk
1.1       christos 2397:        fi
1.2       christos 2398: }
                   2399:
                   2400:
                   2401: getarchsubdirs() {
1.1       christos 2402:        local m
                   2403:        case ${MACHINE_ARCH} in
                   2404:        *arm*|*aarch64*)        m=arm;;
                   2405:        x86_64)                 m=amd64;;
                   2406:        *)                      m=${MACHINE_ARCH};;
                   2407:        esac
                   2408:
1.2       christos 2409:        for i in $(listarchsubdirs); do
                   2410:                echo $i
                   2411:        done | ${SORT} -u | ${SED} -n -e "/=${m}/s@.*=${m}/\(.*\)@\1@p"
1.1       christos 2412: }
                   2413:
                   2414: getcompatlibdirs() {
                   2415:        for i in $(getarchsubdirs); do
1.7       nakayama 2416:                if [ -d "${DEST_DIR}/usr/lib/$i" ]; then
1.1       christos 2417:                        echo /usr/lib/$i
                   2418:                fi
                   2419:        done
                   2420: }
                   2421:
                   2422: #
                   2423: #      obsolete
                   2424: #      (this item is last to allow other items to move obsolete files)
                   2425: #
                   2426: additem obsolete "remove obsolete file sets and minor libraries"
                   2427: do_obsolete()
                   2428: {
                   2429:        [ -n "$1" ] || err 3 "USAGE: do_obsolete  fix|check"
                   2430:        op="$1"
                   2431:        failed=0
                   2432:
                   2433:        ${SORT} -ru "${DEST_DIR}"/var/db/obsolete/* | obsolete_paths "${op}"
                   2434:        failed=$(( ${failed} + $? ))
                   2435:
                   2436:        (
                   2437:                obsolete_libs /lib
                   2438:                obsolete_libs /usr/lib
                   2439:                obsolete_libs /usr/lib/i18n
                   2440:                obsolete_libs /usr/X11R6/lib
                   2441:                obsolete_libs /usr/X11R7/lib
                   2442:                for i in $(getcompatlibdirs); do
                   2443:                        obsolete_libs $i
                   2444:                done
                   2445:        ) | obsolete_paths "${op}"
                   2446:        failed=$(( ${failed} + $? ))
                   2447:
                   2448:        return ${failed}
                   2449: }
                   2450:
                   2451: #
                   2452: #      end of items
                   2453: #      ------------
                   2454: #
                   2455:
                   2456:
                   2457: usage()
                   2458: {
                   2459:        cat 1>&2 << _USAGE_
                   2460: Usage: ${PROGNAME} [-s srcdir] [-x xsrcdir] [-d destdir] [-m mach] [-a arch] op [item [...]]
                   2461:        Perform post-installation checks and/or fixes on a system's
                   2462:        configuration files.
                   2463:        If no items are provided, a default set of checks or fixes is applied.
                   2464:
                   2465:        Options:
                   2466:        -s {srcdir|tgzfile|tempdir}
                   2467:                        Location of the source files.  This may be any
                   2468:                        of the following:
                   2469:                        * A directory that contains a NetBSD source tree;
                   2470:                        * A distribution set file such as "etc.tgz" or
                   2471:                          "xetc.tgz".  Pass multiple -s options to specify
                   2472:                          multiple such files;
                   2473:                        * A temporary directory in which one or both of
                   2474:                          "etc.tgz" and "xetc.tgz" have been extracted.
                   2475:                                                        [${SRC_DIR:-/usr/src}]
                   2476:        -x xsrcdir      Location of the X11 source files.  This must be
                   2477:                        a directory that contains a NetBSD xsrc tree.
                   2478:                                                        [${XSRC_DIR:-/usr/src/../xsrc}]
                   2479:        -d destdir      Destination directory to check. [${DEST_DIR:-/}]
                   2480:        -m mach         MACHINE.                        [${MACHINE}]
                   2481:        -a arch         MACHINE_ARCH.                   [${MACHINE_ARCH}]
                   2482:
                   2483:        Operation may be one of:
                   2484:                help    Display this help.
                   2485:                list    List available items.
                   2486:                check   Perform post-installation checks on items.
                   2487:                diff [diff(1) options ...]
                   2488:                        Similar to 'check' but also output difference of files.
                   2489:                fix     Apply fixes that 'check' determines need to be applied.
                   2490:                usage   Display this usage.
                   2491: _USAGE_
                   2492:        exit 2
                   2493: }
                   2494:
                   2495:
                   2496: list()
                   2497: {
                   2498:        echo "Default set of items (to apply if no items are provided by user):"
                   2499:        echo "  Item          Description"
                   2500:        echo "  ----          -----------"
                   2501:        for i in ${defaultitems}; do
                   2502:                eval desc=\"\${desc_${i}}\"
                   2503:                printf "  %-12s  %s\n" "${i}" "${desc}"
                   2504:        done
                   2505:        echo "Items disabled by default (must be requested explicitly):"
                   2506:        echo "  Item          Description"
                   2507:        echo "  ----          -----------"
                   2508:        for i in ${otheritems}; do
                   2509:                eval desc=\"\${desc_${i}}\"
                   2510:                printf "  %-12s  %s\n" "${i}" "${desc}"
                   2511:        done
                   2512:
                   2513: }
                   2514:
                   2515:
                   2516: main()
                   2517: {
                   2518:        TGZLIST=                # quoted list list of tgz files
                   2519:        SRC_ARGLIST=            # quoted list of one or more "-s" args
                   2520:        SRC_DIR="${SRC_ARG}"    # set default value for early usage()
                   2521:        XSRC_DIR="${SRC_ARG}/../xsrc"
                   2522:        N_SRC_ARGS=0            # number of "-s" args
                   2523:        TGZMODE=false           # true if "-s" specifies a tgz file
                   2524:        DIRMODE=false           # true if "-s" specified a directory
                   2525:        SOURCEMODE=false        # true if "-s" specified a source directory
                   2526:
                   2527:        case "$(uname -s)" in
                   2528:        Darwin)
                   2529:                # case sensitive match for case insensitive fs
                   2530:                file_exists_exact=file_exists_exact
                   2531:                ;;
                   2532:        *)
                   2533:                file_exists_exact=:
                   2534:                ;;
                   2535:        esac
                   2536:
                   2537:        while getopts s:x:d:m:a: ch; do
                   2538:                case "${ch}" in
                   2539:                s)
                   2540:                        qarg="$(shell_quote "${OPTARG}")"
                   2541:                        N_SRC_ARGS=$(( $N_SRC_ARGS + 1 ))
                   2542:                        SRC_ARGLIST="${SRC_ARGLIST}${SRC_ARGLIST:+ }-s ${qarg}"
                   2543:                        if [ -f "${OPTARG}" ]; then
                   2544:                                # arg refers to a *.tgz file.
                   2545:                                # This may happen twice, for both
                   2546:                                # etc.tgz and xetc.tgz, so we build up a
                   2547:                                # quoted list in TGZLIST.
                   2548:                                TGZMODE=true
                   2549:                                TGZLIST="${TGZLIST}${TGZLIST:+ }${qarg}"
                   2550:                                # Note that, when TGZMODE is true,
                   2551:                                # SRC_ARG is used only for printing
                   2552:                                # human-readable messages.
                   2553:                                SRC_ARG="${TGZLIST}"
                   2554:                        elif [ -d "${OPTARG}" ]; then
                   2555:                                # arg refers to a directory.
                   2556:                                # It might be a source directory, or a
                   2557:                                # directory where the sets have already
                   2558:                                # been extracted.
                   2559:                                DIRMODE=true
                   2560:                                SRC_ARG="${OPTARG}"
                   2561:                                if [ -f "${OPTARG}/etc/Makefile" ]; then
                   2562:                                        SOURCEMODE=true
                   2563:                                fi
                   2564:                        else
                   2565:                                err 2 "Invalid argument for -s option"
                   2566:                        fi
                   2567:                        ;;
                   2568:                x)
                   2569:                        if [ -d "${OPTARG}" ]; then
                   2570:                                # arg refers to a directory.
                   2571:                                XSRC_DIR="${OPTARG}"
                   2572:                                XSRC_DIR_FIX="-x ${OPTARG} "
                   2573:                        else
                   2574:                                err 2 "Not a directory for -x option"
                   2575:                        fi
                   2576:                        ;;
                   2577:                d)
                   2578:                        DEST_DIR="${OPTARG}"
                   2579:                        ;;
                   2580:                m)
                   2581:                        MACHINE="${OPTARG}"
                   2582:                        ;;
                   2583:                a)
                   2584:                        MACHINE_ARCH="${OPTARG}"
                   2585:                        ;;
                   2586:                *)
                   2587:                        usage
                   2588:                        ;;
                   2589:                esac
                   2590:        done
                   2591:        shift $((${OPTIND} - 1))
                   2592:        [ $# -gt 0 ] || usage
                   2593:
                   2594:        if [ "$N_SRC_ARGS" -gt 1 ] && $DIRMODE; then
                   2595:                err 2 "Multiple -s args are allowed only with tgz files"
                   2596:        fi
                   2597:        if [ "$N_SRC_ARGS" -eq 0 ]; then
                   2598:                # The default SRC_ARG was set elsewhere
                   2599:                DIRMODE=true
                   2600:                SOURCEMODE=true
                   2601:                SRC_ARGLIST="-s $(shell_quote "${SRC_ARG}")"
                   2602:        fi
                   2603:
                   2604:        #
                   2605:        # If '-s' arg or args specified tgz files, extract them
                   2606:        # to a scratch directory.
                   2607:        #
                   2608:        if $TGZMODE; then
                   2609:                ETCTGZDIR="${SCRATCHDIR}/etc.tgz"
                   2610:                echo "Note: Creating temporary directory ${ETCTGZDIR}"
                   2611:                if ! mkdir "${ETCTGZDIR}"; then
                   2612:                        err 2 "Can't create ${ETCTGZDIR}"
                   2613:                fi
                   2614:                ( # subshell to localise changes to "$@"
                   2615:                        eval "set -- ${TGZLIST}"
                   2616:                        for tgz in "$@"; do
                   2617:                                echo "Note: Extracting files from ${tgz}"
                   2618:                                cat "${tgz}" | (
                   2619:                                        cd "${ETCTGZDIR}" &&
                   2620:                                        tar -zxf -
                   2621:                                ) || err 2 "Can't extract ${tgz}"
                   2622:                        done
                   2623:                )
                   2624:                SRC_DIR="${ETCTGZDIR}"
                   2625:        else
                   2626:                SRC_DIR="${SRC_ARG}"
                   2627:        fi
                   2628:
                   2629:        [ -d "${SRC_DIR}" ]     || err 2 "${SRC_DIR} is not a directory"
                   2630:        [ -d "${DEST_DIR}" ]    || err 2 "${DEST_DIR} is not a directory"
                   2631:        [ -n "${MACHINE}" ]     || err 2 "\${MACHINE} is not defined"
                   2632:        [ -n "${MACHINE_ARCH}" ] || err 2 "\${MACHINE_ARCH} is not defined"
                   2633:        if ! $SOURCEMODE && ! [ -f "${SRC_DIR}/etc/mtree/set.etc" ]; then
                   2634:                err 2 "Files from the etc.tgz set are missing"
                   2635:        fi
                   2636:
                   2637:                # If directories are /, clear them, so various messages
                   2638:                # don't have leading "//".   However, this requires
                   2639:                # the use of ${foo:-/} to display the variables.
                   2640:                #
                   2641:        [ "${SRC_DIR}" = "/" ]  && SRC_DIR=""
                   2642:        [ "${DEST_DIR}" = "/" ] && DEST_DIR=""
                   2643:
                   2644:        detect_x11
                   2645:
                   2646:        op="$1"
                   2647:        shift
                   2648:
                   2649:        case "${op}" in
                   2650:        diff)
                   2651:                op=check
                   2652:                DIFF_STYLE=n                    # default style is RCS
                   2653:                OPTIND=1
                   2654:                while getopts bcenpuw ch; do
                   2655:                        case "${ch}" in
                   2656:                        c|e|n|u)
                   2657:                                if [ "${DIFF_STYLE}" != "n" -a \
                   2658:                                    "${DIFF_STYLE}" != "${ch}" ]; then
                   2659:                                        err 2 "conflicting output style: ${ch}"
                   2660:                                fi
                   2661:                                DIFF_STYLE="${ch}"
                   2662:                                ;;
                   2663:                        b|p|w)
                   2664:                                DIFF_OPT="${DIFF_OPT} -${ch}"
                   2665:                                ;;
                   2666:                        *)
                   2667:                                err 2 "unknown diff option"
                   2668:                                ;;
                   2669:                        esac
                   2670:                done
                   2671:                shift $((${OPTIND} - 1))
                   2672:                ;;
                   2673:        esac
                   2674:
                   2675:        case "${op}" in
                   2676:
                   2677:        usage|help)
                   2678:                usage
                   2679:                ;;
                   2680:
                   2681:        list)
                   2682:                echo "Source directory: ${SRC_DIR:-/}"
                   2683:                echo "Target directory: ${DEST_DIR:-/}"
                   2684:                if $TGZMODE; then
                   2685:                        echo " (extracted from: ${SRC_ARG})"
                   2686:                fi
                   2687:                list
                   2688:                ;;
                   2689:
                   2690:        check|fix)
                   2691:                todo="$*"
                   2692:                : ${todo:="${defaultitems}"}
                   2693:
                   2694:                # ensure that all supplied items are valid
                   2695:                #
                   2696:                for i in ${todo}; do
                   2697:                        eval desc=\"\${desc_${i}}\"
                   2698:                        [ -n "${desc}" ] || err 2 "Unsupported ${op} '"${i}"'"
                   2699:                done
                   2700:
                   2701:                # perform each check/fix
                   2702:                #
                   2703:                echo "Source directory: ${SRC_DIR:-/}"
                   2704:                if $TGZMODE; then
                   2705:                        echo " (extracted from: ${SRC_ARG})"
                   2706:                fi
                   2707:                echo "Target directory: ${DEST_DIR:-/}"
                   2708:                items_passed=
                   2709:                items_failed=
                   2710:                for i in ${todo}; do
                   2711:                        echo "${i} ${op}:"
                   2712:                        ( eval do_${i} ${op} )
                   2713:                        if [ $? -eq 0 ]; then
                   2714:                                items_passed="${items_passed} ${i}"
                   2715:                        else
                   2716:                                items_failed="${items_failed} ${i}"
                   2717:                        fi
                   2718:                done
                   2719:
                   2720:                if [ "${op}" = "check" ]; then
                   2721:                        plural="checks"
                   2722:                else
                   2723:                        plural="fixes"
                   2724:                fi
                   2725:
                   2726:                echo "${PROGNAME} ${plural} passed:${items_passed}"
                   2727:                echo "${PROGNAME} ${plural} failed:${items_failed}"
                   2728:                if [ -n "${items_failed}" ]; then
                   2729:                    exitstatus=1;
                   2730:                    if [ "${op}" = "check" ]; then
                   2731:                        [ "$MACHINE" = "$(uname -m)" ] && m= || m=" -m $MACHINE"
                   2732:                        cat <<_Fix_me_
                   2733: To fix, run:
                   2734:     ${HOST_SH} ${0} ${SRC_ARGLIST} ${XSRC_DIR_FIX}-d ${DEST_DIR:-/}$m fix${items_failed}
                   2735: Note that this may overwrite local changes.
                   2736: _Fix_me_
                   2737:                    fi
                   2738:                fi
                   2739:
                   2740:                ;;
                   2741:
                   2742:        *)
                   2743:                warn "Unknown operation '"${op}"'"
                   2744:                usage
                   2745:                ;;
                   2746:
                   2747:        esac
                   2748: }
                   2749:
1.2       christos 2750: if [ -n "$POSTINSTALL_FUNCTION" ]; then
                   2751:        eval "$POSTINSTALL_FUNCTION"
                   2752:        exit 0
                   2753: fi
                   2754:
1.1       christos 2755: # defaults
                   2756: #
                   2757: PROGNAME="${0##*/}"
                   2758: SRC_ARG="/usr/src"
                   2759: DEST_DIR="/"
                   2760: : ${MACHINE:="$( uname -m )"}  # assume native build if $MACHINE is not set
                   2761: : ${MACHINE_ARCH:="$( uname -p )"}# assume native build if not set
                   2762:
                   2763: DIFF_STYLE=
                   2764: NOT_FIXED=" (FIX MANUALLY)"
                   2765: SCRATCHDIR="$( mkdtemp )" || err 2 "Can't create scratch directory"
                   2766: trap "/bin/rm -rf \"\${SCRATCHDIR}\" ; exit 0" 1 2 3 15        # HUP INT QUIT TERM
                   2767:
                   2768: umask 022
                   2769: exec 3>/dev/null
                   2770: exec 4>/dev/null
                   2771: exitstatus=0
                   2772:
                   2773: main "$@"
                   2774: /bin/rm -rf "${SCRATCHDIR}"
                   2775: exit $exitstatus

CVSweb <webmaster@jp.NetBSD.org>