#!/bin/sh
#
# (C) aryzhov@yahoo.com
#
# Scratch the name_to_major and device tree on the target disk
# and re-generate them so that we have the same majors
# as on the current network-booted kernel
#

#
# ... Generate an extended name_to_major
#


cd /a/etc || exit 0

echo Re-generating the device tree as per booted kernel

if [ -f name_to_major.000 ] ; then
  cp name_to_major name_to_major.`printf '%03d' \`expr \\\`ls name_to_major.??? | tail -1 | cut -d. -f2\\\` + 1\``
else
  cp name_to_major name_to_major.000
fi

cp name_to_major name_to_major.-
cp name_to_major name_to_major.extmajor
cat /etc/name_to_major >name_to_major

CURRENT_NUMBER=`cat name_to_major | awk '{print $2}' | sort -n | tail -1`

cat name_to_major.- | while read drv num ; do
  egrep -s "^$drv " name_to_major && continue
  CURRENT_NUMBER=`expr $CURRENT_NUMBER + 1`
  echo $drv $CURRENT_NUMBER >>name_to_major
done

#
# Re-generate the devices with the new majors
#
mv /a/devices /a/devices.extmajor
mv /a/dev      /a/dev.extmajor
# cd / ; for i in mem null zero devinfo ksyms ; do
#   find dev devices -name \*${i}\* -print
# done | sort | cpio -cdump /a

(cd / && find dev devices -print | cpio -dump /a/.)
devfsadm -r /a 2>&1 | egrep -iv "read-only|path_to_inst"

#
# Walk through the old device tree.
#
# For the clone devices, re-create them.
# If anything else is still missing, mknod it.
#
CMAJOR=`grep '^clone ' /a/etc/name_to_major | awk '{print $2}'`

cd /a/devices.extmajor
find . \( -type c -o -type b -o -type d \) -ls | while read ino ref mode links user group major minor month day time name junk ; do

  DRIVER=`basename $name | cut -d@ -f1`
  [ "$DRIVER" = "." ] && continue
  echo "$DRIVER" | egrep -s "," && continue

  if [ "$DRIVER" = "clone" ] ; then
    i=`echo $name | awk -F: '{print $NF}'`
    newname=/a/devices/pseudo/clone@0:$i
    MINOR=`grep "^$i " /a/etc/name_to_major | awk '{print $2}'`
    [ -z "$MINOR"   -o    ! -c $name ] && continue
    rm -f $newname /a/dev/$i
    mkdir -p `dirname $newname` 2>&-
    mknod $newname c $CMAJOR $MINOR
    ln -s `echo $newname | sed 's?/a?..?g'` /a/dev/$i
  else
    newname=/a/devices/$name
    [ -c $newname   -o   -b $newname ] && continue
    MAJOR=`grep "^$DRIVER " /a/etc/name_to_major | awk '{print $2}'`
    [ -z "$MAJOR" ] && {
      MAJOR=`expr 1 + \`cat /a/etc/name_to_major | awk '{print $2}' | sort -n | tail -1\``
      echo $DRIVER $MAJOR >>/a/etc/name_to_major
    }
    mkdir -p `dirname $newname` 2>&-
    mknod $newname `echo $mode | cut -c1` $MAJOR $minor
  fi

  chmod `ls $name | pkgproto | awk '{print $6}'` $newname
  chown $user:$group $newname

done

#
# Re-create the missing dev links and dirs
#
cd /a/dev.extmajor
find . \( -type l -o -type d \) -ls | awk '{printf("%s\t%s\n", $(NF-2), $NF)}' | while read link target ; do
  newname=/a/dev/$link
  if [ -h $link  -a  ! -h $newname ] ; then
    mkdir -p `dirname $newname` 2>&-
    ln -s $target $newname
  elif [ -d $link   -a   ! -d $newname ] ; then
    mkdir -p $newname
  fi
done

cd /    ; rm -r /a/*.extmajor
