4f6381b784
Use /var/db/obsolete instead of /etc/obsolete etc/Makefile: Create separate target "install-obsolete-files" to populate /var/db/obsolete, instead of using "install-etc-files". Makefile: Add do-obsolete target, to run "cd etc && make install-obsolete-files", and add this to BUILDTARGETS. This moves the "obsolete files" creation from "distribution" to "build". Per discussion with Andrew Brown.
834 lines
18 KiB
Bash
Executable File
834 lines
18 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# $NetBSD: postinstall,v 1.53 2003/02/22 03:20:46 lukem Exp $
|
|
#
|
|
# Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This code is derived from software contributed to The NetBSD Foundation
|
|
# by Luke Mewburn.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. All advertising materials mentioning features or use of this software
|
|
# must display the following acknowledgement:
|
|
# This product includes software developed by the NetBSD
|
|
# Foundation, Inc. and its contributors.
|
|
# 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
# contributors may be used to endorse or promote products derived
|
|
# from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
# postinstall
|
|
# check for or fix configuration changes that occur
|
|
# over time as NetBSD evolves.
|
|
#
|
|
|
|
#
|
|
# checks to add:
|
|
# - obsolete minor/teeny shared libraries in /lib
|
|
# - sysctl(8) renames
|
|
# - de* -> tlp* migration (/etc/ifconfig.de*, $ifconfig_de*,
|
|
# dhclient.conf, ...) ?
|
|
# - support quiet/verbose mode ?
|
|
# - differentiate between failures caused by missing source
|
|
# and real failures
|
|
#
|
|
|
|
#
|
|
# helper functions
|
|
#
|
|
|
|
err()
|
|
{
|
|
exitval=$1
|
|
shift
|
|
echo 1>&2 "${PROGNAME}: $@"
|
|
exit ${exitval}
|
|
}
|
|
|
|
warn()
|
|
{
|
|
echo 1>&2 "${PROGNAME}: $@"
|
|
}
|
|
|
|
msg()
|
|
{
|
|
echo " $@"
|
|
}
|
|
|
|
# additem item description
|
|
# add item to list of supported items to check/fix
|
|
#
|
|
additem()
|
|
{
|
|
[ $# -eq 2 ] || err 2 "USAGE: additem item description"
|
|
items="${items}${items:+ }$1"
|
|
eval desc_$1=\"$2\"
|
|
}
|
|
|
|
# checkdir op dir mode
|
|
# ensure dir exists, and if not, create it with the appropriate mode.
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
check_dir()
|
|
{
|
|
[ $# -eq 3 ] || err 2 "USAGE: check_dir op dir mode"
|
|
_cdop=$1
|
|
_cddir=$2
|
|
_cdmode=$3
|
|
[ -d "${_cddir}" ] && return 0
|
|
if [ "${_cdop}" = "check" ]; then
|
|
msg "${_cddir} is not a directory"
|
|
return 1
|
|
elif ! mkdir -m "${_cdmode}" "${_cddir}" ; then
|
|
msg "Can't create missing ${_cddir}"
|
|
return 1
|
|
else
|
|
msg "Missing ${_cddir} created"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# check_ids op type file id [...]
|
|
# check if file of type "users" or "groups" contains the relevant ids
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
check_ids()
|
|
{
|
|
[ $# -ge 4 ] || err 2 "USAGE: checks_ids op type file id [...]"
|
|
_op=$1
|
|
_type=$2
|
|
_file=$3
|
|
shift 3
|
|
_ids="$@"
|
|
|
|
if [ ! -f "${_file}" ]; then
|
|
msg "${_file} doesn't exist; can't check for missing ${_type}"
|
|
return 1
|
|
fi
|
|
if [ ! -r "${_file}" ]; then
|
|
msg "${_file} is not readable; can't check for missing ${_type}"
|
|
return 1
|
|
fi
|
|
_notfixed=""
|
|
if [ "${_op}" = "fix" ]; then
|
|
_notfixed=${NOT_FIXED}
|
|
fi
|
|
_missing=$(awk -F: '
|
|
BEGIN {
|
|
for (x = 1; x < ARGC; x++)
|
|
idlist[ARGV[x]]++
|
|
ARGC=1
|
|
}
|
|
{
|
|
found[$1]++
|
|
}
|
|
END {
|
|
for (id in idlist) {
|
|
if (! (id in found))
|
|
print id
|
|
}
|
|
}
|
|
' ${_ids} < ${_file}) || return 1
|
|
if [ -n "${_missing}" ]; then
|
|
msg "Missing ${_type}${_notfixed}:" $(echo ${_missing})
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# compare_dir op src dest mode file [file ...]
|
|
# perform op ("check" or "fix") on files in src/ against dest/
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
compare_dir()
|
|
{
|
|
[ $# -ge 5 ] || err 2 "USAGE: compare_dir op src dest mode file [...]"
|
|
_op=$1
|
|
_src=$2
|
|
_dest=$3
|
|
_mode=$4
|
|
shift 4
|
|
_files="$@"
|
|
|
|
if [ ! -d "${_src}" ]; then
|
|
msg "${_src} is not a directory; skipping check"
|
|
return 1
|
|
fi
|
|
check_dir ${_op} ${_dest} 755 || return 1
|
|
|
|
_cmpdir_rv=0
|
|
for f in ${_files}; do
|
|
fs=${_src}/${f}
|
|
fd=${_dest}/${f}
|
|
_error=""
|
|
if [ ! -f "${fd}" ]; then
|
|
_error="${fd} does not exist"
|
|
elif ! cmp -s ${fs} ${fd} ; then
|
|
_error="${fs} != ${fd}"
|
|
else
|
|
continue
|
|
fi
|
|
if [ "${_op}" = "check" ]; then
|
|
msg ${_error}
|
|
_cmpdir_rv=1
|
|
elif ! rm -f ${fd} ||
|
|
! cp -f ${fs} ${fd}; then
|
|
msg "Can't copy ${fs} to ${fd}"
|
|
_cmpdir_rv=1
|
|
elif ! chmod ${_mode} ${fd}; then
|
|
msg "Can't change mode of ${fd} to ${_mode}"
|
|
_cmpdir_rv=1
|
|
else
|
|
msg "Copied ${fs} to ${fd}"
|
|
fi
|
|
done
|
|
return ${_cmpdir_rv}
|
|
}
|
|
|
|
# move_file op src dest --
|
|
# check (op == "check") or move (op != "check") from src to dest.
|
|
# returns 0 if ok, 1 otherwise.
|
|
#
|
|
move_file()
|
|
{
|
|
[ $# -eq 3 ] || err 2 "USAGE: move_file op src dest"
|
|
_fm_op=$1
|
|
_fm_src=$2
|
|
_fm_dest=$3
|
|
|
|
if [ -f "${_fm_src}" -a ! -f "${_fm_dest}" ]; then
|
|
if [ "${_fm_op}" = "check" ]; then
|
|
msg "Move ${_fm_src} to ${_fm_dest}"
|
|
return 1
|
|
fi
|
|
if ! mv ${_fm_src} ${_fm_dest}; then
|
|
msg "Can't move ${_fm_src} to ${_fm_dest}"
|
|
return 1
|
|
fi
|
|
msg "Moved ${_fm_src} to ${_fm_dest}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# rcconf_is_set op name var --
|
|
# load the rcconf for name, and check if obsolete rc.conf(5) variable
|
|
# var is defined or not.
|
|
# returns 0 if defined (even to ""), otherwise 1.
|
|
#
|
|
rcconf_is_set()
|
|
{
|
|
[ $# -eq 3 ] || err 2 "USAGE: rcconf_is_set op name var"
|
|
_rcis_op=$1
|
|
_rcis_name=$2
|
|
_rcis_var=$3
|
|
_rcis_notfixed=""
|
|
if [ "${_rcis_op}" = "fix" ]; then
|
|
_rcis_notfixed=${NOT_FIXED}
|
|
fi
|
|
(
|
|
for f in \
|
|
${DEST_DIR}/etc/rc.conf \
|
|
${DEST_DIR}/etc/rc.conf.d/${_rcis_name}; do
|
|
[ -f "${f}" ] && . "${f}";
|
|
done
|
|
if eval "[ -n \"\${${_rcis_var}}\" \
|
|
-o \"\${${_rcis_var}-UNSET}\" != \"UNSET\" ]"; then
|
|
msg \
|
|
"Obsolete rc.conf(5) variable '\$${_rcis_var}' found.${_rcis_notfixed}"
|
|
exit 0
|
|
else
|
|
exit 1
|
|
fi
|
|
)
|
|
}
|
|
|
|
# find_file_in_dirlist() file message dir1 [...] --
|
|
# find which directory file is in, and sets ${dir} to match
|
|
# returns 0 if matched, otherwise 1 (and sets ${dir} to "").
|
|
#
|
|
# generally, check the directory for the "checking from source" case,
|
|
# and then the directory for the "checking from extracted etc.tgz" case.
|
|
#
|
|
find_file_in_dirlist()
|
|
{
|
|
[ $# -ge 3 ] || err 2 "USAGE: find_file_in_dirlist file msg dir1 [...]"
|
|
|
|
_file=$1 ; shift
|
|
_msg=$1 ; shift
|
|
_dir1st=
|
|
for dir in $*; do
|
|
: ${_dir1st:=${dir}}
|
|
if [ -f "${dir}/${_file}" ]; then
|
|
if [ "${_dir1st}" != "${dir}" ]; then
|
|
msg \
|
|
"(Checking from ${dir} instead of ${_dir1st})"
|
|
fi
|
|
return 0
|
|
fi
|
|
done
|
|
msg "Can't find source directory for ${_msg}"
|
|
return 1
|
|
}
|
|
|
|
|
|
#
|
|
# items
|
|
# -----
|
|
#
|
|
|
|
#
|
|
# rc
|
|
#
|
|
additem postinstall "/etc/postinstall being up to date"
|
|
do_postinstall()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_postinstall fix|check"
|
|
op=$1
|
|
failed=0
|
|
|
|
compare_dir ${op} ${SRC_DIR}/etc ${DEST_DIR}/etc 555 \
|
|
postinstall
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# defaults
|
|
#
|
|
additem defaults "/etc/defaults/ being up to date"
|
|
do_defaults()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_defaults fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc/defaults ${DEST_DIR}/etc/defaults 444 \
|
|
daily.conf monthly.conf rc.conf security.conf weekly.conf
|
|
}
|
|
|
|
#
|
|
# mtree
|
|
#
|
|
additem mtree "/etc/mtree/ being up to date"
|
|
do_mtree()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_mtree fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc/mtree ${DEST_DIR}/etc/mtree 444 \
|
|
NetBSD.dist special
|
|
}
|
|
|
|
#
|
|
# gid
|
|
#
|
|
additem gid "required GIDs"
|
|
do_gid()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_gid fix|check"
|
|
|
|
check_ids $1 groups "${DEST_DIR}/etc/group" \
|
|
named ntpd sshd smmsp
|
|
}
|
|
|
|
#
|
|
# uid
|
|
#
|
|
additem uid "required UIDs"
|
|
do_uid()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_uid fix|check"
|
|
|
|
check_ids $1 users "${DEST_DIR}/etc/master.passwd" \
|
|
named ntpd sshd smmsp
|
|
}
|
|
|
|
|
|
#
|
|
# periodic
|
|
#
|
|
additem periodic "/etc/{daily,weekly,monthly,security} being up to date"
|
|
do_periodic()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_periodic fix|check"
|
|
|
|
compare_dir $1 ${SRC_DIR}/etc ${DEST_DIR}/etc 644 \
|
|
daily weekly monthly security
|
|
}
|
|
|
|
#
|
|
# rc
|
|
#
|
|
additem rc "/etc/rc* and /etc/rc.d/ being up to date"
|
|
do_rc()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_rc fix|check"
|
|
op=$1
|
|
failed=0
|
|
|
|
compare_dir ${op} ${SRC_DIR}/etc ${DEST_DIR}/etc 644 \
|
|
rc rc.subr rc.shutdown
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
compare_dir ${op} ${SRC_DIR}/etc/rc.d ${DEST_DIR}/etc/rc.d 555 \
|
|
DAEMON LOGIN NETWORKING SERVERS accounting altqd amd \
|
|
apmd bootparams bootconf.sh ccd cgd cleartmp cron \
|
|
dhclient dhcpd dhcrelay dmesg downinterfaces fsck \
|
|
ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec isdnd \
|
|
kdc ldconfig lkm1 lkm2 lkm3 local lpd mopd motd \
|
|
mountall mountcritlocal mountcritremote mountd moused \
|
|
mrouted mixerctl named ndbootd network newsyslog nfsd \
|
|
nfslocking ntpd ntpdate poffd postfix ppp pwcheck \
|
|
quota racoon rpcbind raidframe raidframeparity rarpd rbootd \
|
|
root route6d routed rtadvd rtsold rwho savecore \
|
|
screenblank sendmail securelevel sshd staticroute \
|
|
swap1 swap2 sysdb sysctl syslogd timed ttys virecover \
|
|
wdogctl wscons wsmoused \
|
|
xdm xfs ypbind yppasswdd ypserv
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
# check for obsolete rc.d files
|
|
for f in NETWORK fsck.sh kerberos nfsiod servers systemfs \
|
|
daemon gated login portmap sunndd xntpd; do
|
|
fd=${DEST_DIR}/etc/rc.d/${f}
|
|
[ ! -e "${fd}" ] && continue
|
|
if [ "${op}" = "check" ]; then
|
|
msg "Remove obsolete ${fd}"
|
|
failed=1
|
|
elif ! rm ${fd}; then
|
|
msg "Can't remove obsolete ${fd}"
|
|
failed=1
|
|
else
|
|
msg "Removed obsolete ${fd}"
|
|
fi
|
|
done
|
|
|
|
# check for obsolete rc.conf(5) variables
|
|
set -- amd amd_master \
|
|
mountcritlocal critical_filesystems_beforenet \
|
|
mountcritremote critical_filesystems \
|
|
network ip6forwarding \
|
|
sysctl defcorename \
|
|
sysctl nfsiod_flags
|
|
while [ $# -gt 1 ]; do
|
|
if rcconf_is_set ${op} $1 $2; then
|
|
failed=1
|
|
fi
|
|
shift 2
|
|
done
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# ssh
|
|
#
|
|
additem ssh "ssh configuration update"
|
|
do_ssh()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_ssh fix|check"
|
|
op=$1
|
|
|
|
failed=0
|
|
_etcssh=${DEST_DIR}/etc/ssh
|
|
if ! check_dir ${op} ${_etcssh} 755; then
|
|
failed=1
|
|
fi
|
|
|
|
if [ ${failed} -eq 0 ]; then
|
|
for f in \
|
|
ssh_known_hosts ssh_known_hosts2 \
|
|
ssh_host_dsa_key ssh_host_dsa_key.pub \
|
|
ssh_host_rsa_key ssh_host_rsa_key.pub \
|
|
ssh_host_key ssh_host_key.pub \
|
|
; do
|
|
if ! move_file ${op} \
|
|
${DEST_DIR}/etc/${f} ${_etcssh}/${f} ;
|
|
then
|
|
failed=1
|
|
fi
|
|
done
|
|
for f in sshd.conf ssh.conf ; do
|
|
# /etc/ssh/ssh{,d}.conf -> ssh{,d}_config
|
|
#
|
|
if ! move_file ${op} \
|
|
${_etcssh}/${f} ${_etcssh}/${f%.conf}_config ;
|
|
then
|
|
failed=1
|
|
fi
|
|
# /etc/ssh{,d}.conf -> /etc/ssh/ssh{,d}_config
|
|
#
|
|
if ! move_file ${op} \
|
|
${DEST_DIR}/etc/${f} ${_etcssh}/${f%.conf}_config ;
|
|
then
|
|
failed=1
|
|
fi
|
|
done
|
|
fi
|
|
|
|
sshdconf=""
|
|
for f in \
|
|
${_etcssh}/sshd_config \
|
|
${_etcssh}/sshd.conf \
|
|
${DEST_DIR}/etc/sshd.conf ; do
|
|
if [ -f "${f}" ]; then
|
|
sshdconf=${f}
|
|
break;
|
|
fi
|
|
done
|
|
if [ -n "${sshdconf}" ]; then
|
|
awk '
|
|
$1 ~ /^[Hh][Oo][Ss][Tt][Kk][Ee][Yy]$/ &&
|
|
$2 ~ /^\/etc\/+ssh_host(_[dr]sa)?_key$/ {
|
|
sub(/\/etc\/+/, "/etc/ssh/");
|
|
}
|
|
{ print }
|
|
' < ${sshdconf} > ${SCRATCHDIR}/sshd_config
|
|
if ! cmp -s ${sshdconf} ${SCRATCHDIR}/sshd_config; then
|
|
diff ${sshdconf} ${SCRATCHDIR}/sshd_config > \
|
|
${SCRATCHDIR}/sshd_config.diffs
|
|
if [ "${op}" = "check" ]; then
|
|
msg "${sshdconf} needs the following changes:"
|
|
failed=1
|
|
elif ! rm -f ${sshdconf} ||
|
|
! cp -f ${SCRATCHDIR}/sshd_config ${sshdconf}; then
|
|
msg "${sshdconf} changes not applied:"
|
|
failed=1
|
|
else
|
|
msg "${sshdconf} changes applied:"
|
|
fi
|
|
while read _line; do
|
|
msg " ${_line}"
|
|
done < ${SCRATCHDIR}/sshd_config.diffs
|
|
fi
|
|
fi
|
|
|
|
dirsrc=${SRC_DIR}/crypto/dist/ssh
|
|
diretc=${SRC_DIR}/etc
|
|
modulidir=
|
|
if [ -f "${dirsrc}"/moduli ]; then
|
|
modulidir=$dirsrc
|
|
elif [ -f "${diretc}"/moduli ]; then
|
|
modulidir=$diretc
|
|
msg \
|
|
"(Checking for moduli from ${modulidir} instead of ${dirsrc})"
|
|
else
|
|
msg "Can't find source directory for etc/moduli"
|
|
failed=1
|
|
fi
|
|
if [ -n "${modulidir}" ]; then
|
|
if ! compare_dir ${op} ${modulidir} \
|
|
${DEST_DIR}/etc 444 moduli; then
|
|
failed=1
|
|
fi
|
|
fi
|
|
|
|
if ! check_dir "${op}" "${DEST_DIR}/var/chroot/sshd" 755 ; then
|
|
failed=1
|
|
fi
|
|
|
|
if rcconf_is_set ${op} sshd sshd_conf_dir ; then
|
|
failed=1
|
|
fi
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# wscons
|
|
#
|
|
additem wscons "wscons configuration file update"
|
|
do_wscons()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_wscons fix|check"
|
|
op=$1
|
|
|
|
[ -f ${DEST_DIR}/etc/wscons.conf ] || return 0
|
|
|
|
failed=0
|
|
notfixed=""
|
|
if [ "${op}" = "fix" ]; then
|
|
notfixed=${NOT_FIXED}
|
|
fi
|
|
while read _type _arg1 _rest; do
|
|
if [ "${_type}" = "mux" -a "${_arg1}" = "1" ]; then
|
|
msg \
|
|
"Obsolete wscons.conf(5) entry \""${_type} ${_arg1}"\" found.${notfixed}"
|
|
failed=1
|
|
fi
|
|
done < ${DEST_DIR}/etc/wscons.conf
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# makedev
|
|
#
|
|
additem makedev "/dev/MAKEDEV being up to date"
|
|
do_makedev()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_makedev fix|check"
|
|
|
|
find_file_in_dirlist MAKEDEV "MAKEDEV" \
|
|
${SRC_DIR}/etc/etc.${MACHINE} ${SRC_DIR}/dev \
|
|
|| return 1
|
|
|
|
compare_dir $1 ${dir} ${DEST_DIR}/dev 555 MAKEDEV || return 1
|
|
}
|
|
|
|
#
|
|
# postfix
|
|
#
|
|
additem postfix "/etc/postfix/ being up to date"
|
|
do_postfix()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_postfix fix|check"
|
|
op=$1
|
|
failed=0
|
|
|
|
find_file_in_dirlist postfix-script "postfix scripts" \
|
|
${SRC_DIR}/gnu/dist/postfix/conf \
|
|
${DEST_DIR}/usr/share/examples/postfix \
|
|
|| return 1
|
|
|
|
compare_dir ${op} ${dir} ${DEST_DIR}/etc/postfix 555 postfix-script
|
|
failed=$(( ${failed} + $? ))
|
|
compare_dir ${op} ${dir} \
|
|
${DEST_DIR}/etc/postfix 444 post-install postfix-files
|
|
failed=$(( ${failed} + $? ))
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
#
|
|
# obsolete
|
|
#
|
|
additem obsolete "obsolete file sets"
|
|
do_obsolete()
|
|
{
|
|
[ -n "$1" ] || err 2 "USAGE: do_obsolete fix|check"
|
|
op=$1
|
|
|
|
failed=0
|
|
|
|
find_file_in_dirlist base "obsolete set lists" \
|
|
${SRC_DIR}/var/db/obsolete ${DEST_DIR}/var/db/obsolete \
|
|
|| return 1
|
|
|
|
for obssrcfile in ${dir}/*; do
|
|
while read ofile; do
|
|
ofile=${DEST_DIR}${ofile#.}
|
|
cmd="rm"
|
|
ftype="file"
|
|
if [ -h "${ofile}" ]; then
|
|
ftype="link"
|
|
elif [ -d "${ofile}" ]; then
|
|
ftype="directory"
|
|
cmd="rmdir"
|
|
elif [ ! -e "${ofile}" ]; then
|
|
continue
|
|
fi
|
|
if [ "${op}" = "check" ]; then
|
|
msg "Remove obsolete ${ftype} ${ofile}"
|
|
failed=1
|
|
elif ! eval ${cmd} ${ofile}; then
|
|
msg "Can't remove obsolete ${ftype} ${ofile}"
|
|
failed=1
|
|
else
|
|
msg "Removed obsolete ${ftype} ${ofile}"
|
|
fi
|
|
done < ${obssrcfile}
|
|
done
|
|
|
|
return ${failed}
|
|
}
|
|
|
|
|
|
#
|
|
# end of items
|
|
# ------------
|
|
#
|
|
|
|
|
|
usage()
|
|
{
|
|
cat 1>&2 << _USAGE_
|
|
Usage: ${PROGNAME} [-s srcdir] [-d destdir] [-m machine] operation [item [...]]
|
|
Perform post-installation checks and/or fixes on a system's
|
|
configuration files.
|
|
If no items are provided, all checks or fixes are applied.
|
|
|
|
Options:
|
|
-s srcdir Source directory to compare from. [${SRC_DIR:-/}]
|
|
-d destdir Destination directory to check. [${DEST_DIR:-/}]
|
|
-m machine Machine architecture. [${MACHINE}]
|
|
|
|
Operation may be one of:
|
|
help display this help
|
|
list list available items
|
|
check perform post-installation checks on items
|
|
fix apply fixes that 'check' determines need to be applied
|
|
usage display this usage
|
|
_USAGE_
|
|
exit 1
|
|
}
|
|
|
|
|
|
list()
|
|
{
|
|
echo "Supported items:"
|
|
echo " Item Description"
|
|
echo " ---- -----------"
|
|
for i in ${items}; do
|
|
eval desc="\${desc_${i}}"
|
|
printf " %-12s %s\n" "${i}" "${desc}"
|
|
done
|
|
}
|
|
|
|
|
|
main()
|
|
{
|
|
while getopts s:d:m: ch; do
|
|
case ${ch} in
|
|
s)
|
|
SRC_DIR=${OPTARG} ;;
|
|
d)
|
|
DEST_DIR=${OPTARG} ;;
|
|
m)
|
|
MACHINE=${OPTARG} ;;
|
|
*)
|
|
usage ;;
|
|
esac
|
|
done
|
|
shift $((${OPTIND} - 1))
|
|
[ $# -gt 0 ] || usage
|
|
|
|
[ -d "${SRC_DIR}" ] || err 1 "${SRC_DIR} is not a directory"
|
|
[ -d "${DEST_DIR}" ] || err 1 "${DEST_DIR} is not a directory"
|
|
[ -n "${MACHINE}" ] || err 1 "\${MACHINE} is not defined"
|
|
|
|
# If directories are /, clear them, so various messages
|
|
# don't have leading "//". However, this requires
|
|
# the use of ${foo:-/} to display the variables.
|
|
#
|
|
[ "${SRC_DIR}" = "/" ] && SRC_DIR=""
|
|
[ "${DEST_DIR}" = "/" ] && DEST_DIR=""
|
|
|
|
op=$1
|
|
shift
|
|
|
|
case "${op}" in
|
|
|
|
usage|help)
|
|
usage
|
|
;;
|
|
|
|
list)
|
|
echo "Source directory: ${SRC_DIR:-/}"
|
|
echo "Target directory: ${DEST_DIR:-/}"
|
|
list
|
|
;;
|
|
|
|
check|fix)
|
|
todo="$@"
|
|
: ${todo:=${items}}
|
|
|
|
# ensure that all supplied items are valid
|
|
#
|
|
for i in ${todo}; do
|
|
eval desc=\"\${desc_${i}}\"
|
|
[ -n "${desc}" ] || err 1 "Unsupported ${op} '"${i}"'"
|
|
done
|
|
|
|
# perform each check/fix
|
|
#
|
|
echo "Source directory: ${SRC_DIR:-/}"
|
|
echo "Target directory: ${DEST_DIR:-/}"
|
|
items_passed=
|
|
items_failed=
|
|
for i in ${todo}; do
|
|
echo "${i} ${op}:"
|
|
( eval do_${i} ${op} )
|
|
if [ $? -eq 0 ]; then
|
|
items_passed="${items_passed} ${i}"
|
|
else
|
|
items_failed="${items_failed} ${i}"
|
|
fi
|
|
done
|
|
|
|
if [ "${op}" = "check" ]; then
|
|
plural="checks"
|
|
else
|
|
plural="fixes"
|
|
fi
|
|
|
|
echo "${PROGNAME} ${plural} passed:${items_passed}"
|
|
echo "${PROGNAME} ${plural} failed:${items_failed}"
|
|
if [ -n "${items_failed}" -a "${op}" = "check" ]; then
|
|
[ "$MACHINE" = "$(uname -m)" ] && m= || m=" -m $MACHINE"
|
|
cat <<_Fix_me_
|
|
To fix, run:
|
|
${0} -s ${SRC_DIR} -d ${DEST_DIR:-/}$m fix${items_failed}
|
|
_Fix_me_
|
|
fi
|
|
|
|
;;
|
|
|
|
*)
|
|
warn "Unknown operation '"${op}"'"
|
|
usage
|
|
;;
|
|
|
|
esac
|
|
}
|
|
|
|
mkdtemp ()
|
|
{
|
|
# Make sure we don't loop forever if mkdir will always fail.
|
|
[ -d /tmp ] || err 1 /tmp is not a directory
|
|
[ -w /tmp ] || err 1 /tmp is not writable
|
|
|
|
_base=/tmp/_postinstall.$$
|
|
_serial=0
|
|
|
|
while true; do
|
|
_dir=${_base}.${_serial}
|
|
mkdir -m 0700 ${_dir} && break
|
|
_serial=$((${_serial} + 1))
|
|
done
|
|
echo ${_dir}
|
|
}
|
|
|
|
# defaults
|
|
#
|
|
PROGNAME=${0##*/}
|
|
SRC_DIR="/usr/src"
|
|
DEST_DIR="/"
|
|
: ${MACHINE:=$( uname -m )} # assume native build if $MACHINE is not set
|
|
|
|
NOT_FIXED=" [NOT FIXED]"
|
|
SCRATCHDIR=$( mkdtemp ) || err 1 "Can't create scratch directory"
|
|
trap "/bin/rm -rf ${SCRATCHDIR} ; exit 0" 0 1 2 3 15 # EXIT HUP INT QUIT TERM
|
|
|
|
umask 022
|
|
|
|
main "$@"
|
|
exit 0
|