Article Listing 1 apr2005.tar

Listing 1 Makeinstall

#!/usr/dt/bin/dtksh
 
# Type "makeinstall help=y" for online man page.

function my_getopts {
#- version 3.141592, 2002-02-02, Michael Wang <xw73@columbia.edu>.
  typeset PATH= SEP= i
  typeset -u _I
  for i; do
    _I=$i
    eval ${_I%%?(:)=*}= unset ${_I%%?(:)=*}
    case $_I in
      *[!:]=*) eval $(IFS=$SEP; print ${_I%%=*}=\"${_I#*=}\")   ;;
      *:=*)    eval $(IFS=$SEP; print ${_I%%:=*}=\"${i#*:=}\")  ;;
    esac
  done
}

function kshdoc {
# version 2.0, 2003-05-08, Michael Wang <xw73@columbia.edu>.
  typeset path file base tdir;
  typeset -u help

  eval help=y "$@"

  typeset -x PATH=${path:-$PATH}

  whence perldoc >/dev/null || {
    [[ -x /usr/perl5/bin/perldoc ]] && PATH=$PATH:/usr/perl5/bin
    whence perldoc >/dev/null || {
      print "You need to have perldoc in your PATH."
      return 1
    }
  }

  [[ $help = @(Y|PS|PDF) ]] && {
    base=${file##*/}; base=${base%.@(ksh|sh|ss)}
    tdir=/tmp/$base.$$.$RANDOM
    mkdir $tdir && trap "rm -rf $tdir" EXIT
    sed -n '/^## =/,${/^##/s/^## \{0,1\}//p;}' $file > $tdir/$base.pod
    case $help in
      Y)   if (( $(id -u) == 0 )); then
             su bin -c "perldoc $tdir/$base.pod"
           else
             perldoc $tdir/$base.pod
           fi;;
      PS)  pod2man $tdir/$base.pod | groff -man > $base.ps;;
      PDF) pod2man $tdir/$base.pod | groff -man | ps2pdf - $base.pdf;;
    esac
  }

  return 0
}

[[ $1 == help=y ]] && { kshdoc file=$0 help=y; exit 0; }

function do_snapshot {
  typeset fs=${1} sr=${2} bs=${3} mp dv ix
  for ix in ${fs//:/ }; do
    mp=${sr}${ix/%"/"/"/root"}
    mkdir -p $mp
    mount -F ufs -o ro $(fssnap -F ufs -o bs=${bs},unlink $ix) $mp
    fssnap -i -o blockdevname $ix | awk "{print \$NF}" | read dv &&
    df -Pk $mp | grep "^$dv" || return 1
  done
}

# Reason for awk "{print \$NF}":
# fssnap -i -o blockdevname /fs
# Solaris 8: /dev/fssnap/0
# Solaris 9: Block Device : /dev/fssnap/0

function undo_snapshot {
  typeset fs=${1} sr=${2} mp ix
  for ix in ${fs//:/ }; do
    mp=${sr}${ix/%"/"/"/root"}
    umount $mp
    fssnap -F ufs -d $ix
    ! fssnap -i -o blockdevname $ix | awk "{print \$NF}" | read &&
    ! df -Pk $mp | grep "^/dev/fssnap/[0-9]\{1,\}" || return 1
  done
}

function find_diff {
  typeset fs=${1} sr=${2} md=${3} mp ix iy
  typeset -u an
  for ix in ${fs//:/ }; do
    mp=${sr}${ix/%"/"/"/root"}
    print ${ix}:
    if [[ $md == new2old ]]; then
      rsync -vanx --delete ${ix}/ ${mp}/
    else
      rsync -vanx --delete ${mp}/ ${ix}/
      print -n "commit? "
      read an
      [[ $an == Y* ]] && rsync -vax --delete ${mp}/ ${ix}/
    fi
  done
}

function find_fs {
  typeset fs=$1
  [[ -n "$fs" && $fs != [+-]* ]] && print $fs && return 0

  typeset i j k
  df -Pk -F ufs | while read i; do
    set -- $i
    j=${@:$#:1}
    [[ $j == @(/|/usr|/var|/opt) ]] && {
      [[ $fs == -?(*:)${j}?(:*) ]] || k="$k:$j"
    }
  done

  if [[ $fs == +* ]]
  then print ${k}:${fs#+}
  else print ${k}
  fi
}

set -e

PATH=$(/bin/getconf PATH)
PATH=$PATH:/usr/sbin
PATH=$PATH:/opt/csw/bin

my_getopts HELP=N "$@"
: ${SNAPROOT:=/snapshot}
: ${STEP:=0}
: ${BS:=$(< $SNAPROOT/.backing-store)}
# fs:=

FS=$(find_fs $FS)

[[ $STEP == *1* || $STEP == 9 ]] &&   do_snapshot $FS $SNAPROOT $BS
[[ $STEP == *2* || $STEP == 9 ]] && {
  print    "type make install or whatever in another window."
  print -n "ready? "
  read
}
[[ $STEP == *3* || $STEP == 9 ]] && find_diff     $FS $SNAPROOT "new2old"
[[ $STEP == *4* || $STEP == 9 ]] && find_diff     $FS $SNAPROOT "old2new"
[[ $STEP == *5* || $STEP == 9 ]] && {
  if [[ $STEP == 5 ]]
  then an=Y
  else print -n "delete snapshots? "
       read an
  fi
  [[ $an == [Yy]* ]] && undo_snapshot $FS $SNAPROOT
}

exit 0

## =head1 NAME
##
## B<makeinstall> - capture file system changes with snapshot and rsync
##
## =head1 SYNOPSIS
##
## ...