-p = pause after every stage
-o = OS upgrade only, no packages or other software
-h = this help
-d = path to upgrade data (should be autodetermined)
-r = path to mounted root filesystem to upgrade
EOF
}
dir=""
root=""
pause=""
osonly=""
while getopts pd:ohr: OPTION
do
case $OPTION in
p) pause=y
;;
d) dir="$OPTARG"
;;
r) root="$OPTARG"
;;
o) osonly=y
;;
h|?) usage
exit 1
;;
esac
done
shift `expr $OPTIND - 1`
if [ -z "$root" ]; then
echo "Please specify location of installed system with -r flag"
exit 1
fi
if [ ! -f $root/netbsd ]; then
echo "No existing install found at $root"
exit 1
fi
if [ -z "$dir" ]; then
dir=`echo $0 | awk -F/ '
BEGIN {
if(substr("'$0'",1,1)!="/") printf "'$PWD'/"
}
{
for (i=1;i<NF-1;i++) printf"%s/",$i
print $(NF-1)
}'`
fi
if [ ! -f $dir/amd64/binary/sets/base.tgz ]; then
echo "Could not locate the NetManager CD"
echo "Please specify a path using the -d option"
exit 1
fi
dopause()
{
local r
[ -z "$pause" ] && return
echo -n "Press RETURN to continue"
read r
}
readbin()
{
local file READELF elf
file=$1
READELF=""
if [ -z "$file" ]; then
echo "No file given to readbin" > /dev/stderr
return 3
fi
if [ ! -f "$root/$file" ]; then
echo "file $file does not exist" > /dev/stderr
return 3
fi
if [ -x /usr/bin/readelf ]; then
READELF=/usr/bin/readelf
elif [ -x $root/usr/bin/readelf ]; then
READELF="env LD_LIBRARY_PATH=$root/lib:$root/usr/lib $root/usr/bin/readelf"
else
echo "Could not locate readelf binary"
return 2
fi
[ -z "$READELF" ] && return 2
elf=`$READELF -hn $root/$file | awk '{
if ($1 == "Machine:") {
machine = $2
for (n = 3; n <= NF; n++) machine = machine " " $n
}
if ($1 == "NetBSD" && $3 == "IDENT") {
l = length($4)
v = 0+substr($4, 1, l-8)
}
if ($1 == "NetBSD" && $3 == "NT_VERSION") {
v = $2
}
}
END{
printf "%s/%s\n", v, machine
}'`
case "${elf%/*}" in
5|7)
bvers="${elf%/*}"
;;
0x00000004)
bvers=5
;;
*)
echo "Existing $file binary is for unknown OS version ${elf%/*}"
return 1
;;
esac
case "${elf#*/}" in
*80386)
barch=i386
;;
*x86_64|*X86-64)
barch="x86_64"
;;
*)
echo "Existing $file binary is for unknown architecture: ${elf#*/}"
return 1
;;
esac
echo "$barch/$bvers"
return 0
}
sets=$dir/$machine/binary/sets
# Stage 1: check free space
free=`df -m $root | awk -v root=$root '{if ($6 == root) print $4}'`
if [ -z "$free" ]; then
echo "$root is not a mountpoint"
exit 1
fi
if [ "$free" -lt 500 ]; then
echo "Not enough free space to upgrade ($free MB)"
exit 1
fi
# Stage 2: check installed kernel
if [ ! -f $root/netbsd ]; then
echo "Cannot find installed kernel"
exit 1
fi
if [ -x /usr/bin/config ]; then
CONFIG=/usr/bin/config
elif [ -x $root/usr/bin/config ]; then
CONFIG=$root/usr/bin/config
else
echo "Could not locate config binary"
exit 1
fi
### START CONFIG FILE "/usr/src/5.0/sys/arch/i386/conf/NETMANXEN3"
kv=`$CONFIG -x $root/netbsd | awk 'BEGIN{
q = sprintf("%c", 34)
}
{
if ($1 == "###" && $2 == "START" && $3 == "CONFIG" && $4 == "FILE") {
c = $5
gsub(q, "", c)
n = split(c, p, "/")
printf "%s/%s\n", p[n], p[n-2]
}
}'`
if [ -z "$kv" ]; then
echo "Could not determine kernel type"
exit 1
fi
kname=${kv%/*}
kmachine=${kv#*/}
kerntype=`readbin netbsd`
if [ "$?" != 0 ]; then
echo "Could not read kernel type"
exit 1
fi
echo "Kernel:$kname Machine:$kmachine Release:$kerntype"
dopause
if [ "$kerntype" != "$machine/$version" ]; then
case "$kname" in
XEN3PAE_DOMU|XEN3PAE_DOMUNMB)
kname="XEN3_DOMU"
;;
GENERICNMB)
kname="GENERIC"
;;
esac
if [ -f $dir/build/version/$version/$machine/kernels/$kname.tgz ]; then
kf=$dir/build/version/$version/$machine/kernels/$kname.tgz
elif [ -f $dir/amd64/binary/sets/kern-$kname.tgz ]; then
kf=$dir/amd64/binary/sets/kern-$kname.tgz
else
echo "Cannot find kernel for $version"
exit 1
fi
echo "Copying old kernel"
cp $root/netbsd $root/netbsd.old
echo "Installing kernel for $machine version $version"
export kf
(cd $root ; tar -xpzf $kf || exit 1) || exit 1
else
echo "Kernel already installed"
fi
# Stage 3: check /dev
dopause
lnod=`ls -l /dev/wd1a | awk '/^b/{ printf "%s%s\n", $5, $6}'`
tnod=`ls -l $root/dev/wd1a | awk '/^b/{ printf "%s%s\n", $5, $6}'`
if [ "$lnod" != "$tnod" ]; then
echo "Creating /dev for $machine"
(cd $root ; tar -xpzf $sets/etc.tgz ./dev/MAKEDEV || exit 1) || exit 1
(cd $root/dev ; sh MAKEDEV all || exit 1) || exit 1
else
echo "/dev already updated for $machine"
fi
lastfile=`tar -tvzf $sets/xserver.tgz | awk 'BEGIN {
s = sprintf("%c.so%c.[0-9]+$", 92, 92)
}
{
if ($1 ~ "^-r.[sx]..x..x$") lfile = $9
else if ($9 ~ s) lfile = $9
}
END {
if (substr(lfile, 1, 2) == "./") lfile = substr(lfile, 3)
print lfile
}'`
if [ -z "$lastfile" ]; then
echo "Cannot determine last file in archive"
continue_n
runup=1
oldversion="Unknown"
else
runup=0
oldversion=`readbin $lastfile`
ret=$?
case "$ret" in
1)
continue_n
;;
2)
continue_n
runup=1
;;
esac
if [ "$oldversion" = "$arch/$version" ]; then
echo "Userland already upgraded"
echo -n "Run userland upgrade again? (y/n) [n]:"
read resp
[ "$resp" = y ] && runup=1
else
runup=1
fi
[ -z "$oldversion" ] && oldversion="Unknown"
fi
if [ "$runup" = 1 ]; then
echo "Upgrading userland from $oldversion to $arch/$version"
cd $root
if [ -d $root/usr/X11R7/lib/X11/xkb/symbols/pc ]; then
rm -r $root/usr/X11R7/lib/X11/xkb/symbols/pc
fi
for i in base comp games man misc modules \
tests text \
xbase xcomp xfont xserver
do
echo "Extracting $i"
tar -xpzf $sets/$i.tgz || continue_n
done || exit 1
tar -xpzf $sets/etc.tgz ./etc/rc.d ./etc/rc.subr ./etc/defaults \
./etc/man.conf
rm -f ./etc/ld.so.conf ./etc/rc.d/lkm ./etc/rc.d/btattach \
./etc/rc.d/btconfig ./etc/rc.d/btdevctl ./etc/rc.d/poffd
fi
for u in _rtadvd:30:/var/chroot/rtadvd \
_gpio:29:/nonexistent \
_tss:28:/var/tpm \
_tcpdump:27:/var/chroot/tcpdump \
_tests:26:/nonexistent \
_mdnsd:17:/nonexistent \
_httpd:24:/var/www \
_timedc:22:/nonexistent
do
user=${u%%:*}
u=${u#*:}
uid=${u%%:*}
u=${u#*:}
home=${u%%:*}
cuser=`awk -F: -v user=$user -v gfile=$root/etc/group \
-v uid=$uid -v min=75 -v max=99 'BEGIN {
while((getline line < gfile) >0) {
split(line, gr, ":")
gid[gr[3]] = gr[1]
gname[gr[1]] = gr[3]
}
}
{
if ($3 == uid) {
cname=$1
if (cgid == "") cgid=$4
}
if ($1 == user) {
cuid=$3
cgid=$4
}
if ($3 >= min && $3 <= max) id[$3] = $1
}
END {
scangroup = 0
if (cuid != "") {
cname=user
}
else if (user in gname) {
usegid = gname[user]
cgid = usegid
}
else if (uid in gid) {
if (gid[uid] != user) scangroup = 1
else cgid = uid
} else {
cgid = uid
}
if ((cname != user && cname != "") || scangroup == 1) {
for (n = min; n <= max; n++) if (n in id) {
} else {
if (scangroup == 1) {
if (n in gid)
if (gid[n] != user) continue
}
cuid = n
cgid = n
n = max
}
}
usegid = cgid
if (cgid in gid) {
if (gid[cgid] == user) cgid = ""
}
printf "%s:%s:%s:%s\n", cname, cuid, usegid, cgid
}' $root/etc/ptmp`
# echo ${cuser}
cname=${cuser%%:*}
cuser=${cuser#*:}
cuid=${cuser%%:*}
cuser=${cuser#*:}
usegid=${cuser%%:*}
cuser=${cuser#*:}
cgid=${cuser%%:*}
# echo "$user:$uid $cname:$cuid $cgid"
if [ -n "$cgid" ]; then
echo "Create group $user with GID $cgid"
echo "$user:*:$cgid:" >> $root/etc/group
fi
createuser=""
if [ -z "$cname" ]; then
createuser=1
if [ -z "$cuid" ]; then
echo "Create user $user with UID $uid and GID $usegid"
cuid=$uid
else
echo "Create user $user with UID $cuid instead of $uid. GID $usegid"
fi
elif [ "$cname" != "$user" ]; then
createuser=1
echo "Create user $user with UID $cuid because of $cname having UID $uid. GID $usegid"
fi
if [ -n "$createuser" ]; then
echo "$user:*:$cuid:$usegid::0:0:& pseudo-user:$home:/sbin/nologin" >> $root/etc/ptmp
fi
done
echo "Rebuilding password database"
pwd_mkdb -p -d $root $root/etc/ptmp || exit 1
sync;sync
echo "Preparing for postinstall"
dopause
if [ -d $root/usr/X11R7/lib/X11/xkb/symbols/pc ]; then
rm -r $root/usr/X11R7/lib/X11/xkb/symbols/pc
fi
for f in 10-autohint 10-no-sub-pixel 10-sub-pixel-bgr \
10-sub-pixel-rgb 10-sub-pixel-vbgr \
10-sub-pixel-vrgb 10-unhinted 25-unhint-nonlatin \
65-khmer 70-no-bitmaps 70-yes-bitmaps
do
[ -f $root/etc/fonts/conf.d/${f}.conf ] && rm $root/etc/fonts/conf.d/${f}.conf
done
if [ -d $root/etc/disklabels ]; then
if [ -d $root/etc/netmanager ]; then
mv $root/etc/disklabels $root/etc/netmanager/disklabels
else
mv $root/etc/disklabels $root/etc/disklabels.old
fi
fi
mkdir -p $root/postup
cd $root/postup
tar -xpzf $sets/etc.tgz
tar -xpzf $sets/xetc.tgz
tasks=`$root/usr/sbin/postinstall -s $root/postup list | awk 'BEGIN{
output=0
}
{
if ($1 == "----") output++
if ($1 == "uid" || $1 == "gid" || $1 == "Item") next
if ($0~"^[[:space:]]+[a-zA-Z]" && output == 1) print $1
}'`
if [ $root != / ]; then
echo "Running postinstall in chroot"
chroot $root /usr/sbin/postinstall -s /postup fix uid gid
chroot $root /usr/sbin/postinstall -s /postup fix $tasks
piexit=$?
else
echo "Running postinstall directly"
/usr/sbin/postinstall -s /postup fix uid gid
/usr/sbin/postinstall -s /postup fix $tasks
piexit=$?
fi
cd /
rm -r $root/postup
if [ "$piexit" != 0 ]; then
continue_n
fi
#echo "Fixing mail INBOX location"
#if [ -d $root/var/mail -a -d $root/usr/mail ]; then
# rmdir $root/var/mail
# if [ "$?" != 0 ]; then
# echo "Could not delete /var/mail"
# exit 1
# fi
# ln -s /usr/mail $root/var/mail
#fi
if [ "$osonly" = y ]; then
echo "Completed. Warning: your old packages are still installed"
exit
fi
echo "Removing all packages for wrong architecture or OS version"
dopause
for pkg in `pkg_info -K $root/var/db/pkg | awk '{print $1}'`
do
delete=""
parch=`pkg_info -K $root/var/db/pkg -Q MACHINE_ARCH $pkg 2>/dev/null`
if [ -z "$parch" ]; then
echo "$pkg has already been deleted"
elif [ "$parch" != $arch ]; then
echo "Deleting $pkg for $parch"
delete=1
else
pvers=`pkg_info -K $root/var/db/pkg -Q OS_VERSION $pkg`
pversmaj=`echo $pvers|awk '{print substr($1,1,1)}'`
cvers=`echo $version|awk '{print substr($1,1,1)}'`
if [ "$pversmaj" != "$cvers" ]; then
echo "Deleting $pkg for $pvers"
delete=1
fi
fi
if [ -n "$delete" ]; then
if [ "$root" = / ]; then
pkg_delete -fr $pkg || exit 1
else
chroot $root /usr/sbin/pkg_delete -fr $pkg || exit 1
fi
fi
done