#!/bin/ash
#LGPL Copyright 2006,2007 Barry Kauler, www.puppylinux.com
#2006,2007 contributions by Dougal, Pakt, Mitch, Jesse, Steven, Kirk

PATH="/bin"
KERNVER="`uname -r`"
NTFSDEV=""

#Boot param PMEDIA= usbflash|usbhd|usbcd|ideflash|idehd|idecd|idezip|satahd|scsihd|scsicd
# ...good, as will know exactly what drivers to load and where to look.
#v2.15 allow 'PMEDIA=cd' a subset, could be ide, sata, usb or scsi cd drive.
[ $pmedia ] && PMEDIA=$pmedia #v2.15 support lower-case.
#v2.15 PDEV1 now can be boot param. ex: PDEV1=hda1  allow lower-case...
[ $pdev1 ] && PDEV1=$pdev1
#v2.16 boot param, subdirectory with Puppy files...
[ $psubdir ] && PSUBDIR="$psubdir"
[ ! $PSUBDIR ] && PSUBDIR="boot" #default place to look.
#v2.16rc... unless boot override, only aufs if booting from flash drive...
# (otherwise use unionfs)
if [ ! $aufs ];then
 [ "`echo -n "$PMEDIA" | grep 'flash'`" != "" ] && aufs=1
fi

#note, in tables below, all partitions and files mount on "/".

#unionfs layers:            RW            RO1             RO2              PUPMODE
#PUPSFS only:               tmpfs                         pup_xxx.sfs      5
#PDEV1 has puppy:           tmpfs         PDEV1*                           3
#PDEV1 has puppy, no tmpfs: PDEV1                                          2 (do not use initrd.gz)
#PDEV1, PUPSFS:             tmpfs         PDEV1*          pup_xxx.sfs      7
#PDEV1, PUPSFS, no tmpfs:   PDEV1                         pup_xxx.sfs      6

#pup_save.3fs is an ext3 f.s. file. If this exists, then the file, not PDEV1,
#has our personal Puppy data. In that case:

#unionfs layers:            RW            RO1             RO2              PUPMODE
#found PUPSFS, PUPSAVE:     tmpfs         pup_save.3fs*   pup_xxx.sfs      13
#PUPSAVE(multi), PUPSFS:    tmpfs         folders(tmpfs2) pup_xxx.sfs      13+64 = 77
#PUPSAVE, PUPSFS, no tmpfs: pup_save.3fs                  pup_xxx.sfs      12
#PUPSAVE(multi), PUPSFS:    folders(tmpfs)                pup_xxx.sfs      5+64 = 69
 
# * persistent storage (RO1) is actually mounted rw, though ro in union.

#now supporting a boot menu...
if [ "$pfix" ];then
 #allow comma-delimited values for pfix...
 PFIXPRMS="`echo -n "$pfix" | tr ',' ' '`"
 for ONEFIX in $PFIXPRMS
 do
 case $ONEFIX in
  ram)     PRAMONLY="yes";;      #run in ram only.
  rdsh)    RDSH="yes";;          #exit to shell in initial ramdisk.
  rdsh5)   RDSH="5";;            #exit just before unionfs activated.
  usbcard) USBCARD="yes";;       #boot from pcmcia drive.
  clean)   PCLEAN="yes";;        #v2.13 force version upgrade and cleanup.
  purge)   PPURGE="yes";;        #v2.14 radical cleanup for broken system.
  nox)     PNOX="yes";;          #v2.15 do not start X.
  debug)   DEBUG="yes";;         #v2.10 dougal suggested this.
  [0-9]*)  PIGNORELAST=$ONEFIX;; #blacklist last $ONEFIX folders (multisession).
  *)       PLOOKONLY="$pfix";;   #NOT YET IMPLEMENTED
 esac
 done
fi

check_status()
{
  /bin/echo -en "\\033[70G" >/dev/console #v2.15 change 65 to 70
  if [ $1 -eq 0 ]
  then
    /bin/echo -en "\\033[1;32mdone" >/dev/console
    /bin/echo -e "\\033[0;39m" >/dev/console
  else
    /bin/echo -en "\\033[1;31mfailed" >/dev/console
    /bin/echo -e "\\033[0;39m" >/dev/console
    echo -en "\\033[1;35m" >/dev/console #35=purple
    echo -n "Dumping last lines of /tmp/bootinit.log..." >/dev/console
    /bin/echo -e "\\033[0;39m" >/dev/console
    echo -en "\\033[1;31m" >/dev/console #31=red
    cat /tmp/bootinit.log | tail -n 4 >/dev/console
    /bin/echo -en "\\033[0;39m" >/dev/console
    echo -en "\\033[1;35m" >/dev/console #35=purple
    echo -n "Dumping last lines of kernel log..." >/dev/console
    /bin/echo -e "\\033[0;39m" >/dev/console
    echo -en "\\033[1;31m" >/dev/console #31=red
    dmesg | tail -n 4 >/dev/console
    /bin/echo -en "\\033[0;39m" >/dev/console
    #v2.16 exit to initial ramdisk shell...
    [ "$RDSH" = "yes" ] && exec /bin/sh >/dev/console 2>&1
    echo "Pausing for 60 seconds..." >/dev/console
    sleep 60
  fi
}

fsfunc() #f.s. type param passed in
{
 FSTYPE="$1"
 [ "$FSTYPE" = "Ext2" ] && FSTYPE="ext2"
 [ "$FSTYPE" = "ReiserFS" ] && FSTYPE="reiserfs"
 [ "$FSTYPE" = "Ext3" ] && FSTYPE="ext3"
 [ "$FSTYPE" = "FAT16" ] && FSTYPE="vfat"
 [ "$FSTYPE" = "FAT32" ] && FSTYPE="vfat"
 [ "$FSTYPE" = "NTFS" ] && FSTYPE="ntfs"
 [ "$FSTYPE" = "ISO9660" ] && FSTYPE="iso9660"
 [ "$FSTYPE" = "msdos" ] && FSTYPE="vfat"
}

mntfunc() {
 if [ "`echo "$@" | grep 'ntfs'`" = "" ];then
  mount $@
  MNTVAL=$?
 else
  #MNTPRMS="`echo "$@" | sed -e 's/\-t[^a-zA-Z0-9/]*ntfs//g'`" #screen out '-t ntfs'
  #MNTPRMS="`echo -n "$@" | tr '\t' ' ' | tr -s ' ' | sed -e 's/ \-t ntfs/ /g'`" #screen out '-t ntfs'
  #screen out -o and -t options...
  MNTPRMS="`echo -n "$@" | tr '\t' ' ' | tr -s ' ' | tr ' ' '\n' | grep '^/' | tr '\n' ' '`"
  #kirk advised these options so Rox will not complain about file
  #permissions when copy a file to a ntfs partition...
  ntfs-3g $MNTPRMS -o silent,umask=0,no_def_opts,allow_other 2>/dev/null
  MNTVAL=$?
  if [ $MNTVAL -eq 4 -o $MNTVAL -eq 10 ];then #v2.16 addd 10.
   #MNTPRMS="`echo "$MNTPRMS" | sed -e 's/\-o[^a-zA-Z0-9/]*[a-zA-Z0-9,]*//g'`" #screen out '-o xxx'
   #MNTPRMS="`echo -n "$MNTPRMS" | tr '\t' ' ' | tr -s ' ' | sed -e 's/\-o [a-zA-Z0-9,]*//g'`" #screen out '-o xxx'
   #add the 'force' option...
   ntfs-3g $MNTPRMS -o force,silent,umask=0,no_def_opts,allow_other 2>/dev/null #default is rw,noatime
   MNTVAL=$?
  fi
  [ $MNTVAL -eq 0 ] && NTFSDEV="`echo -n "$MNTPRMS" | cut -f 1 -d ' '`"
 fi
 return $MNTVAL
}

umntfunc() {
 #warning, umntfunc call must not have trailing comment.
 #warning umntfunc call must have mntpt param, not device name.
 #LASTPARAM="`echo "$@" |  sed -e 's/^.*[^a-zA-Z0-9/]//g'`"
 LASTPARAM="`echo -n "$@" | tr '\t' ' ' | tr -s ' ' | tr ' ' '\n' | grep '^/mnt/'`"
 if [ "`mount | grep "$LASTPARAM" | grep -E 'ntfs|fuse'`" = "" ];then
  umount $@
  MNTVAL=$?
 else
  fusermount -u $LASTPARAM
  MNTVAL=$?
  [ $MNTVAL -eq 0 ] && NTFSDEV=""
 fi
 return $MNTVAL
}

#v2.14
record_fnd_func() {
 #$1=f.s. $2=dev $3 = mount point.  Example: vfat sda1 /mnt/data
 #find out if any puppy files here and record to PUPFOUND variable.
 echo -n " ${2}..." >/dev/console
 ALLFILES="`ls -1 -r $3`"
 #v2.16 now recognise puppy files in /boot directory...
 if [ -d ${3}/$PSUBDIR ];then #PSUBDIR defaults to 'boot'
  PPATTERN="s%^%${PSUBDIR}/%g"
  BOOTFILES="`ls -1 -r ${3}/boot | sed -e "$PPATTERN"`"
  [ "$BOOTFILES" != "" ] && ALLFILES="$ALLFILES
$BOOTFILES"
 fi
 #look for 'pup_save' files...
 for ONESAVE in `echo -n "$ALLFILES" | grep 'pup_save.*\.[23]fs$'`
 do
  PUPFOUND="${PUPFOUND}${1},${2},/${ONESAVE},PPUPSAVE
"
 done
 
 #manual install of zdrv_xxx.sfs in ntfs/vfat may be capitals...
 [ "${1}" = "ntfs" ] && [ -f ${3}/ZDRV_${PUPPYVERSION}.SFS ] && mv -f ${3}/ZDRV_${PUPPYVERSION}.SFS ${3}/zdrv_${PUPPYVERSION}.sfs
 [ "${1}" = "vfat" ] && [ -f ${3}/${PSUBDIR}/ZDRV_${PUPPYVERSION}.SFS ] && mv -f ${3}/${PSUBDIR}/ZDRV_${PUPPYVERSION}.SFS ${3}/${PSUBDIR}/zdrv_${PUPPYVERSION}.sfs #v2.16rc

 #look for '.sfs' files...
 #for ONESFS in `find ./ -mount -maxdepth 1 -type f -name *.sfs | sed -e 's/^\.//g'`
 PPATTERN="${PUPPYVERSION}\.sfs$"
 for ONESFS in `echo -n "$ALLFILES" | grep "$PPATTERN"`
 do
  PKEYWORD='PMORESFS'
  [ "$ONESFS" = "pup_${PUPPYVERSION}.sfs" ] && PKEYWORD='PPUPSFS'
  [ "$ONESFS" = "zdrv_${PUPPYVERSION}.sfs" ] && PKEYWORD='PZDRVSFS'
  [ "$ONESFS" = "${PSUBDIR}/pup_${PUPPYVERSION}.sfs" ] && PKEYWORD='PPUPSFS' #v2.16
  [ "$ONESFS" = "${PSUBDIR}/zdrv_${PUPPYVERSION}.sfs" ] && PKEYWORD='PZDRVSFS' #v2.16
  PUPFOUND="${PUPFOUND}${1},${2},/${ONESFS},${PKEYWORD}
"
 done
 
 #v2.15 may need to know where initrd.gz is (humongous initrd)...
 [ -f ${3}/initrd.gz ] && PUPFOUND="${PUPFOUND}${1},${2},/initrd.gz,PINITRDGZ
"
 #v2.16 look in /boot...
 [ -f ${3}/${PSUBDIR}/initrd.gz ] && PUPFOUND="${PUPFOUND}${1},${2},/${PSUBDIR}/initrd.gz,PINITRDGZ
"
 
 #find out if multisession folders...
 BKFOLDER="`echo -n "$ALLFILES" | grep '^20[0-9][0-9]\-[0-9]' | head -n 1`"
 #windows partition may have a file with name 20* so test if directory...
 [ "$BKFOLDER" ] && [ -d ${3}/$BKFOLDER ] &&  PUPFOUND="${PUPFOUND}${1},${2},/${BKFOLDER},PPUPFOLDER
"
 #is there a full installation to the partition (not just frugal)?...
 if [ -f ${3}/etc/puppyversion ];then
  INSTVER="`cat ${3}/etc/puppyversion`"
  #ignore puppy1 installation...
  [ "`echo "$INSTVER" | grep "^1"`" = "" ] && PUPFOUND="${PUPFOUND}${1},${2},${INSTVER},PPUPFULL
"
 fi
 #look for a swap file...
 [ -f ${3}/WIN386.SWP ] &&  PUPFOUND="${PUPFOUND}${1},${2},/WIN386.SWP,PSWAPFILE
"
 [ -f ${3}/PAGEFILE.SYS ] &&  PUPFOUND="${PUPFOUND}${1},${2},/PAGEFILE.SYS,PSWAPFILE
"
 [ -f ${3}/pup.swp ] &&  PUPFOUND="${PUPFOUND}${1},${2},/pup.swp,PSWAPFILE
"
} #end record_fnd_func

#v2.14
analyse_pupfound_func() {
 #search_drives_func writes to PUPFOUND, all found puppy-related files. now analyse...
 #PUPFOUND has format:  f.s.,dev,/filename,keyword  Example: vfat,sda1,/pup_save.2fs,PPUPSAVE
 #there is a param passed in, 'boot' or 'save':
 #boot: called only once, used for identifying boot device and files in it.
 #save: if 'boot' failed to find the pup_save file, for booting from cd, searchsavefunc
 #searches the drives and calls this func with 'save', looking for the pup_save file.
 #searchsavefunc calls record_fnd_func then analyse_pupfound_func for each partition
 #until it finds pup_save.
 PASSEDPARAM=$1
 
 #what did boot off?...
 #v2.16 humongous initrd, need fallback test for boot device...
 if [ "$PASSEDPARAM" = "boot" ];then
  PUPSFS="" #v2.16rc moved up.
  ZDRV="" #v2.16rc moved up.
  PBOOTDEV="`echo "$PUPFOUND" | grep "PINITRDGZ" | head -n 1 | cut -f 2 -d ','`"
  PBOOTFS="`echo "$PUPFOUND" | grep "PINITRDGZ" | head -n 1 | cut -f 1 -d ','`"
  if [ ! -f /pup_$PUPPYVERSION.sfs ];then
   #normal situation...
   #must find initrd.gz and pup_xxx.sfs together...
   FPATTERN=",${PBOOTDEV},"
   PBOOTDEV="`echo "$PUPFOUND" | grep "PPUPSFS" | grep "$FPATTERN" | cut -f 2 -d ','`"
   PBOOTFS="`echo "$PUPFOUND" | grep "PPUPSFS" | grep "$FPATTERN" | cut -f 1 -d ','`"
  else #v2.16rc
   #humongous initrd....
   PUPSFS="rootfs,rootfs,/pup_$PUPPYVERSION.sfs"
   #[ -f /zdrv_$PUPPYVERSION.sfs ] && ZDRV="rootfs,rootfs,/zdrv_$PUPPYVERSION.sfs"
   #....no, wrong. zdrv file will be found by modprobe. see symlink created near end of script.
  fi
 fi
 
 #where is the pup_save file?...
 PNORMSAVES="`echo "$PUPFOUND" | grep 'PPUPSAVE' | cut -f 1-3 -d ','`"
 PMULTISAVES="`echo "$PUPFOUND" | grep 'PPUPFOLDER' | cut -f 1-3 -d ','`"
 #what partitions have a full installation of puppy (not just frugal)?...
 PFULLINSTALLS="`echo "$PUPFOUND" | grep 'PPUPFULL' | cut -f 1-3 -d ','`"

 #the main puppy .sfs file...
 PPUPSFS="`echo "$PUPFOUND" | grep 'PPUPSFS' | cut -f 1-3 -d ','`"

 #find extra .sfs files...
 PMORESFS="`echo "$PUPFOUND" | grep 'PMORESFS' | cut -f 1-3 -d ','`"
 
 #find zdrv file...
 PZDRV="`echo "$PUPFOUND" | grep 'PZDRVSFS' | cut -f 1-3 -d ','`"
 
 #the info that this script needs is (prior to v2.14):
 #PDEV1=partition have booted off         Example: sda1
 #FSTYPE=f.s. of boot partition           Example: vfat
 #PUPSFS=pup_xxx.sfs                      Example: pup_214.sfs
 #...v2.16 format change: PUPSFS="vfat,hda1,/pup_216.sfs"
 #DEV1PUP='yes' means PDEV1 partition has a full installation of puppy (not frugal)
 #PUPSAVE='pup_save' file chosen to use   Example: vfat,sda1,/pup_save.2fs

 NAMEPUPSFS="pup_$PUPPYVERSION.sfs"
 if [ "$PASSEDPARAM" = "boot" ];then 
  #Note: now allowing PDEV1 to be a boot parameter. record_fnd_func handles this.
  PDEV1="$PBOOTDEV"
  FSTYPE="$PBOOTFS"
  #PUPSFS=""
  DEV1PUP=""
  #ZDRV=""
  if [ "$PDEV1" ];then
   DPATTERN="${PDEV1},"
   [ ! "$PUPSFS" ] && [ "$PPUPSFS" ] && PUPSFS="`echo "$PPUPSFS" | grep "$DPATTERN"`"
   #PUPSFS="${FSTYPE},${PDEV1},/pup_${PUPPYVERSION}.sfs"
   [ ! "`echo "$PFULLINSTALLS" | grep "$DPATTERN"`" = "" ] && DEV1PUP='yes'
   #extra .sfs files in boot partition...
   MORE1SFS="`echo -n "$PMORESFS" | grep "$DPATTERN" | cut -f 2 -d '/' | tr '\n' ' '`"
   #...Variable MORE1SFS is a space-delimited list of extra .sfs files
   #found at same place as pup_xxx.sfs, used in multisession-loading function.
   [ ! "$ZDRV" ] && [ "$PZDRV" ] && ZDRV="`echo "$PZDRV" | grep "$DPATTERN" | head -n 1`"
  fi
 fi
 
 #choosing the correct pup_save file is involved...
 CRYPTO="";MSGCHOICE=""
 if [ ! "$PRAMONLY" ];then #pfix=ram boot menu option.
  if [ "$PMULTISAVES" ];then
   PUPSAVE="`echo "$PMULTISAVES" | head -n 1`"
  else
   if [ "$PNORMSAVES" ];then
    #if booting from anything other than CD, restrict search to PDEV1...
    if [ "`echo -n "$PMEDIA" | grep 'cd'`" = "" ];then
     if [ "$PDEV1" ];then
      DPATTERN="${PDEV1},"
      PNORMSAVES1="`echo "$PNORMSAVES" | grep "$DPATTERN"`"
      if [ "$PNORMSAVES1" = "" ];then
       MSGCHOICE="WARNING: RECOMMEND CHOOSE '0', AS NORMALLY YOU WOULD USE A 'pup_save' FILE
IN THE BOOT MEDIA (created at shutdown). TYPE '0' NOW!
"
      else
       PNORMSAVES="$PNORMSAVES1" #use pup_save(s) in boot media only.
      fi
     fi
    fi
   fi
   if [ "$PNORMSAVES" ];then
    NUMLINES="`echo "$PNORMSAVES" | wc -l  | tr -s " " | cut -f 2 -d " "`"
    [ "$MSGCHOICE" != "" ] && NUMLINES=2 #arbitrary not-1.
    if [ "$NUMLINES" = "1" ];then
     PUPSAVE="$PNORMSAVES" #only one, so use it.
     savename="`echo -n "$PUPSAVE" | cut -f 2 -d '/'`"
     savepart="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
     echo -n "Using personal data file $savename which is on partition $savepart" >/dev/console
    else
     CNT3FS=1
     echo -e "\\033[1;36m" >/dev/console #34=blue, 33=yellow, 32=green, 31=red, 35=purple, 36=aquablue, 38=black.
     echo "${MSGCHOICE}PLEASE CHOOSE WHICH PERSONAL FILE TO USE" >/dev/console
     echo "0  none" >/dev/console
     CHOICES3FS="`echo -n "$PNORMSAVES" | tr "\n" " "`"
     for ONE3FS in $CHOICES3FS
     do
      onefs="`echo -n "$ONE3FS" | cut -f 1 -d ','`"
      onepart="`echo -n "$ONE3FS" | cut -f 2 -d ','`"
      onefn="`echo -n "$ONE3FS" | cut -f 3 -d ',' | sed -e 's/^\///g'`"
      oneuser="`echo -n "$onefn" | grep '_crypt' | sed -e 's/.*_crypt//g' | cut -f 2 -d '-' | cut -f 1 -d '.'`"
      if [ "$oneuser" = "" ];then
       echo "$CNT3FS  $onefn (in partition ${onepart})" >/dev/console
      else
       echo -n "$CNT3FS '$oneuser'" >/dev/console
       echo -en "\\033[19G" >/dev/console #move to column 19
       echo "(file $onefn, in partition ${onepart})" >/dev/console
      fi
      CNT3FS=`expr $CNT3FS + 1`
     done
     echo -n "Please type a number then press ENTER key: " >/dev/console
     echo -en "\\033[0;39m" >/dev/console
     read NUM3FS
     clear
     if [ $NUM3FS -gt 0 ];then
      PUPSAVE="`echo -n "$CHOICES3FS" | cut -f $NUM3FS -d " "`"
      savename="`echo -n "$PUPSAVE" | cut -f 2 -d '/'`"
      savepart="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
      echo -n "Using personal data file $savename which is on partition $savepart" >/dev/console
     else
      #this func can get recalled, so get rid of rejected pup_saves...
      PUPFOUND="`echo "$PUPFOUND" | grep -v 'PPUPSAVE'`"
     fi
    fi
    if [ "$PUPSAVE" ];then
     check_status 0 #need new-line after above msg.
     # Kirk's encryption code (slightly modified by Dougal and BK)...
     if [ ! "`echo "$PUPSAVE" | grep '_crypt'`" = "" ];then
      case $PUPSAVE in 
       *cryptx*) #see /etc/rc.d/rc.shutdown.
        CRYPTO='-E 1' #v2.16final '-e xor' --bug, loads xor.ko which is something else.
        zcat /modules/${KERNVER}/cryptoloop.ko.gz | insmod -
        ;;
       *)
        CRYPTO='-e aes'
        zcat /modules/${KERNVER}/cryptoloop.ko.gz | insmod -
        zcat /modules/${KERNVER}/aes.ko.gz | insmod -
        ;;
      esac
     fi
    fi
   fi
  fi
 fi
 
 if [ "$PASSEDPARAM" = "save" ];then
  #any *.sfs files in boot part. should be copied to same part. as pup_save.2fs...
  #yeah, live-cd will copy *.sfs to same partition as pup_save...
  XTRAPUPSFS=""
  if [ "$PUPSAVE" ];then
   if [ "`echo "$PMEDIA" | grep 'cd$'`" != "" ];then
    #this script (about line 1148) reads XTRAPUPSFS and will load pup_xxx.sfs off
    #the hard drive instead of cd...
    savepartd="`echo -n "$PUPSAVE" | cut -f 2 -d ','`,"
    [ "$PPUPSFS" != "" ] && XTRAPUPSFS="`echo "$PPUPSFS" | grep "$savepartd"`"
    if [ "$XTRAPUPSFS" = "" ];then
     savepart="`echo -n "$PUPSAVE" | cut -f 2 -d ','` "
     savepartd="$savepart "
     #but not if pup_save is on slow and/or small storage...
     SMALLSAVE="`echo -n "$USBDRIVES $ZIPDRIVES " | grep "$savepartd"`"
     [ "$SMALLSAVE" = "" ] && SMALLSAVE="`echo -n "$savepart" | grep 'fd'`" #floppy
     if [ "$SMALLSAVE" = "" ];then
      savemntpt2=""
      savefs="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"
      dsavefsd=" $savefs "
      savemntpt="`mount | grep "$savepartd" | grep "$dsavefsd" | cut -f 3 -d ' '`"
      if [ "$savemntpt" = "" ];then
       mount -t $savefs /dev/$savepart /mnt/data2
       if [ $? -eq 0 ];then
        savemntpt="/mnt/data2"
        savemntpt2="$savemntpt"
       fi
      fi
      if [ "$savemntpt" != "" ];then
       if [ "$PUPSFS" ];then
        if [ ! -f $savemntpt/$NAMEPUPSFS ];then
         sfspartd="`echo -n "$PUPSFS" | cut -f 2 -d ','` "
         dsfsfsd=" `echo -n "$PUPSFS" | cut -f 1 -d ','` "
         sfsmntpt="`mount | grep "$sfspartd" | grep "$dsfsfsd" | cut -f 3 -d ' '`"
         if [ "$sfsmntpt" = "" ];then
          mount -t $dsfsfsd /dev/$sfspartd /mnt/data
          cp -f /mnt/data/*.sfs $savemntpt/
          sync
          umount /mnt/data
         else
          cp -f $sfsmntpt/*.sfs $savemntpt/
          sync
         fi
        fi
       fi
       #has the pup_xxx.sfs file been copied to a fast media?...
       if [ -f $savemntpt/$NAMEPUPSFS ];then
        PUPSFS="$savefs,$savepart,/$NAMEPUPSFS"
        XTRAPUPSFS="$PUPSFS"
       fi
       #has the zdrv file been copied to a fast media?...
       [ -f $savemntpt/zdrv_${PUPPYVERSION}.sfs ] && ZDRV="$savefs,$savepart,/zdrv_${PUPPYVERSION}.sfs"
      fi
      [ "$savemntpt2" != "" ] && umount $savemntpt2
     fi
    fi
   fi
  fi
 fi
 
 #printout to test...
 echo "PDEV1=$PDEV1"
 echo "FSTYPE=$FSTYPE"
 echo "PUPSFS=$PUPSFS"
 echo "DEV1PUP=$DEV1PUP"
 echo "PUPSAVE=$PUPSAVE"
 echo "ZDRV=$ZDRV"
 #save results of all passes through this func...
 PUPFNDACC="$PUPFNDACC
$PUPFOUND"
} #end analyse_pupfound_func

search_drives_func() {
 #find all puppy-related components on drives...
 #passed in: list-of-drives  example: sda sdb
 #local TESTDRVS,TESTPARTS,MPATTERN,SUPERFLOPPYS,ONEDRIVE
 TESTDRVS="$@"
 echo -n "Looking for Puppy in" >/dev/console
 #if PDEV1 boot param, reduce to searching that only...
 [ "$PDEV1" ] && TESTDRVS="`echo -n "$PDEV1" | sed -e 's/[0-9]//g'`"
 for ONEDRIVE in $TESTDRVS
 do
  TESTPARTS="`echo "$PCPARTS0" | grep "$ONEDRIVE" | tr "\n" " "`"
  #note, TESTPARTS has the format 'hda1|vfat hda2|ext2 '
  #if PDEV1 a boot param with partition number, then ignore other parts... v2.16rc fix...
  [ ! "`echo -n "$PDEV1" | grep '[0-9]'`" = "" ] && [ ! "`echo -n "$TESTPARTS" | grep "$PDEV1"`" = "" ] && TESTPARTS="`echo "$PCPARTS0" | grep "$PDEV1 "`"
  #is it a cd?...
  if [ ! "`echo "$TESTPARTS" | grep "iso9660"`" = "" ];then
   mntfunc -t iso9660 /dev/$ONEDRIVE /mnt/data 2> /dev/null
   if [ $? -eq 0 ];then
    record_fnd_func iso9660 $ONEDRIVE /mnt/data #writes all fnd puppy files to PUPFOUND.
    umntfunc /mnt/data
   fi
   continue
  fi
  #is it a superfloppy?...
  MPATTERN="${ONEDRIVE}: unknown partition table"
  if [ ! "`dmesg | grep "$MPATTERN"`" = "" ];then
   SUPERFLOPPYFS="`disktype /dev/$ONEDRIVE | grep "file system" | grep "^[a-zA-Z]" | head -n 1 | cut -f 1 -d " "`"
   if [ "$SUPERFLOPPYFS" ];then
    fsfunc $SUPERFLOPPYFS #sets FSTYPE
    mntfunc -t $FSTYPE /dev/$ONEDRIVE /mnt/data 2> /dev/null
    if [ $? -eq 0 ];then
     record_fnd_func $FSTYPE $ONEDRIVE /mnt/data #writes all fnd puppy files to PUPFOUND.
     umntfunc /mnt/data
    fi
   fi
   continue
  fi
  #must be drive with partitions...
  for TESTONE in $TESTPARTS
  do
   TRYPART="`echo -n "$TESTONE" | cut -f 1 -d '|'`"
   TRYFS="`echo -n "$TESTONE" | cut -f 2 -d '|'`"
   fsfunc $TRYFS #sets FSTYPE
   mntfunc -t $FSTYPE /dev/$TRYPART /mnt/data 2> /dev/null
   if [ $? -eq 0 ];then
    record_fnd_func $FSTYPE $TRYPART /mnt/data #writes all fnd puppy files to PUPFOUND.
    umntfunc /mnt/data
   fi
  done
 done
 check_status 0
 analyse_pupfound_func boot
} #end search_drives_func


#v2.10 jesse...
usbstoragefunc() {
 WAITUSB=""
 if [ ! "$USB" = "" ];then
  #k2.6: annoying, lsmod reports usb-storage.ko as usb_storage if loaded...
  if [ "`lsmod | grep "^usb_storage"`" = "" ];then
   #any /dev/sd drives will be sata at this time...
   SATADRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"
   echo "USB-Storage: Loading usb-storage module"
   #zcat /modules/${KERNVER}/usb/usb-storage.ko.gz | insmod - &
   [ ! -f /modules/${KERNVER}/usb/usb-storage.ko ] && gunzip /modules/${KERNVER}/usb/usb-storage.ko.gz
   insmod /modules/${KERNVER}/usb/usb-storage.ko &
   WAITUSB="yes" #see usbstoragecompletionfunc
   TIMEOUTUSB=50 #read in usbstoragecompletionfunc
  fi
 fi
} #end usbstoragefunc

#v2.10 jesse...
usbstoragecompletionfunc() {
 WAITUSB=""
 if [ ! "`lsmod | grep "^usb_storage"`" = "" ];then #precaution.
  echo -n "USB-Storage: Detecting connected device(s)..."
  SLPCNT=0;USBSTORAGES=0;AVAILABLEUSBSTORAGES=0
  while true;do
   sleep 1 #v2.10r1
   #v2.15 busybox 1.4.1 grep not accept -o option....
   #USBSTORAGES=`/bin/dmesg | grep -o "usb-storage: device found at.*" | wc -l | sed -e 's/ //g'`
   USBSTORAGES=`/bin/dmesg | grep "usb-storage: device found at" | wc -l | sed -e 's/ //g'`
   AVAILABLEUSBSTORAGES=`/bin/dmesg | grep "usb-storage: device scan complete" | wc -l | sed -e 's/ //g'`
   if [ $USBSTORAGES -eq $AVAILABLEUSBSTORAGES ]; then
    #v2.10r1 booting from usb...
    if [ ! "`echo -n "$PMEDIA" | grep "usb"`" = "" ];then
     if [ $AVAILABLEUSBSTORAGES -eq 0 ];then #0 not acceptable
      #sleep 1
      continue
     fi
    fi
    echo
    echo "USB-Storage: Device scan complete, found $AVAILABLEUSBSTORAGES devices"
    break
   fi
   if [ $SLPCNT -gt $TIMEOUTUSB ]; then
    echo
    echo "USB-Storage: Device scan time-out $SLPCNT secs, found $AVAILABLEUSBSTORAGES of $USBSTORAGES device(s)."
    break
   fi
   #sleep 1
   SLPCNT=`expr $SLPCNT + 1`
   echo -n " $SLPCNT"
  done
 fi
} #end usbstoragecompletionfunc

guesspmediafunc() {
 #guess PMEDIA, as was not provided as boot param.
 PMEDIA="int"
 [ "$FSTYPE" = "iso9660" ] && PMEDIA="cd"
 #[ ! "`echo -n "$PDEV1" | grep '^sd'`" = "" ] && PMEDIA="usbflash"
 PDEVDRV="`echo -n "$PDEV1" | cut -b 1-3`"
 [ ! "`echo -n "$USBDRIVES" | grep "$PDEVDRV"`" = "" ] && PMEDIA="usbflash"
 [ ! "`echo -n "$SATADRIVES" | grep "$PDEVDRV"`" = "" ] && PMEDIA="satahd"
 [ ! "`echo -n "$IDEDRIVES" | grep "$PDEVDRV"`" = "" ] && PMEDIA="idehd"
 [ ! "`echo -n "$ZIPDRIVES" | grep "$PDEVDRV"`" = "" ] && PMEDIA="idezip"
} #end guesspmediafunc

loadfolders() { #source folder, dest. folder passed in.
 #source folder is where the multisession cd is mounted.
 #dest dir has a tmpfs mntd on it, into which to copy folders.
 CDMNTPT="$1"
 DESTDIR="$2"

 BKFOLDERS="`ls -1 -r $CDMNTPT | grep '^20[0-9][0-9]'`"
 BKLASTFOLDER="`echo "$BKFOLDERS" | head -n 1`"

 #a boot option allows ignore last n sessions, also need to create a badlist...
 if [ "$PIGNORELAST" ];then
  BKBADLIST="`echo "$BKFOLDERS" | head -n ${PIGNORELAST}`"
  if [ -f $CDMNTPT/$BKLASTFOLDER/.badfolders ];then
   cp $CDMNTPT/$BKLASTFOLDER/.badfolders $DESTDIR/
   if [ ! $? -eq 0 ];then
    #fallback, in case last folder badly corrupted...
    BKPREVFOLDER="`echo "$BKFOLDERS" | head -n 2 | tail -n 1`"
    [ -f $CDMNTPT/$BKPREVFOLDER/.badfolders ] && cp $CDMNTPT/$BKPREVFOLDER/.badfolders $DESTDIR/
   fi
  fi
  echo "$BKBADLIST" >> $DESTDIR/.badfolders
  #note, rc.shutdown and savesession-dvd 'touch' this file so it will get saved.
  sync
 else
  [ -f $CDMNTPT/$BKLASTFOLDER/.badfolders ] && cp $CDMNTPT/$BKLASTFOLDER/.badfolders $DESTDIR/
 fi
 [ -f $DESTDIR/.badfolders ] && BKBADLIST="`cat $DESTDIR/.badfolders | tr "\n" " "`"

 BKFOLDERS="`echo -n "$BKFOLDERS" | tr "\n" " "`"
 for ONEFOLDER in $BKFOLDERS
 do
  if [ ! "`echo -n "$BKBADLIST" | grep "$ONEFOLDER"`" = "" ];then
   echo "Folder $ONEFOLDER marked bad." >/dev/console
   continue #ignore bad folder.
  fi
  echo -n "Loading folder $ONEFOLDER from CD/DVD..." >/dev/console
  #need to be careful not to overfill the ramdisk...
  FREERAMDISK=`df 2>/dev/null | grep "$DESTDIR" | head -n 1 | tr -s " " | cut -f 4 -d " "`
  SIZEFOLDER=`du -k -s ${CDMNTPT}/${ONEFOLDER} | cut -f 1`
  if [ -d ${CDMNTPT}/${ONEFOLDER}/archive ];then
   SIZEARCHIVE=`du -k -s ${CDMNTPT}/${ONEFOLDER}/archive | cut -f 1`
  else
   SIZEARCHIVE=0
  fi
  SIZESOURCE=`expr $SIZEFOLDER - $SIZEARCHIVE`

  if [ $FREERAMDISK -gt $SIZESOURCE ];then
   #well, -u will only copy if files newer, so less stuff may get copied than calc'd above.
   #need to copy everything except archive folder...
   #cp -a -u $CDMNTPT/$ONEFOLDER/[^archive]* $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/bin ] && cp -a -u $CDMNTPT/$ONEFOLDER/bin $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/sbin ] && cp -a -u $CDMNTPT/$ONEFOLDER/sbin $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/etc ] && cp -a -u $CDMNTPT/$ONEFOLDER/etc $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/lib ] && cp -a -u $CDMNTPT/$ONEFOLDER/lib $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/opt ] && cp -a -u $CDMNTPT/$ONEFOLDER/opt $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/root ] && cp -a -u $CDMNTPT/$ONEFOLDER/root $DESTDIR/   > /dev/null 2>&1
   [ -d $CDMNTPT/$ONEFOLDER/usr ] && cp -a -u $CDMNTPT/$ONEFOLDER/usr $DESTDIR/   > /dev/null 2>&1
   #delete deleted files (.wh.filename)...
   WHITEOUTS="`find $DESTDIR -type f -mount -name .wh.* | grep -v '__dir_opaque'`"
   echo "$WHITEOUTS" |
   while read DELWHITE
   do
    DELFILE="`echo -n "$DELWHITE" | sed -e 's/\.wh\.//g'`"
    if [ -e "$DELFILE" ];then
     rm -rf "$DELFILE"
     rm -rf "$DELWHITE"
    fi
   done
   check_status 0 #v2.16 display 'done' for each folder loaded.
  else
   echo -e "\\033[70G\\033[1;31mRAM full\\033[0;39m" >/dev/console #red text on column 70.
   break
  fi
 done
 sync
} #end loadfolders

#v2.15 make executables in pup_xxx.sfs available to initial-ramdisk...
enable_all_execs() {
 case $PUPMODE in
  2) PUPFILESDIR="/pup_new" ;;
  3) PUPFILESDIR="/pup_ro1" ;;
  *) PUPFILESDIR="/pup_ro2" ;;
 esac
 if [ -d $PUPFILESDIR/usr ];then #precaution
  ln -s $PUPFILESDIR/usr /usr
  ln -s $PUPFILESDIR/lib /lib
  echo "/usr/lib" >> /etc/ld.so.conf
 else
  PUPFILESDIR=""
 fi
} #end enable_all_execs

loadpupsfsfunc() { #mnt pt of PDEV1 is passed parameter (normally /mnt/dev_ro1).
 #mounts pup_xxx.sfs file on /pup_ro2...
 #enter with PDEV1 (boot partition) already mounted (usually on /mnt/dev_ro1).
 #v2.15 handle humongous initrd...
 if [ -f /pup_$PUPPYVERSION.sfs ];then
  NAMEPUPSFS="pup_$PUPPYVERSION.sfs"
  PUPSFS="rootfs,rootfs,/${NAMEPUPSFS}"
  #need to move it to a tmpfs (later moved to pup_new) as switch_root obliterates "ramdisk"...
  SIZEPUPSFSK=`du /$NAMEPUPSFS | cut -f 1`
  SIZEPUPSFSK=`expr $SIZEPUPSFSK + 1000` #some slack.
  mount tmpfs /mnt/tmpfs -t tmpfs -o size=${SIZEPUPSFSK}k;check_status $?
  mv -f /$NAMEPUPSFS /mnt/tmpfs/
  echo -n "Mounting (/initrd)/mnt/tmpfs/$NAMEPUPSFS on (/initrd)/pup_ro2..." >/dev/console
  losetup /dev/loop0 /mnt/tmpfs/$NAMEPUPSFS
  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2;check_status $?
  sync
  umntfunc ${1}
  return
 fi
 #v2.16 PUPSFS now has full format: vfat,hda2,/pup_215.sfs...
 sfspart="`echo -n "$PUPSFS" | cut -f 2 -d ','`"
 sfspartd="$sfspart "
 sfsfs="`echo -n "$PUPSFS" | cut -f 1 -d ','`"
 sfsmntpt="`mount | grep "$sfspartd" | cut -f 3 -d ' '`"
 if [ "$sfsmntpt" = "" ];then
  sfsmntpt="$1"
  sfspart="$PDEV1"
 fi
  #if enough room in ramdisk, copy it...
  SIZEPUPSFSK=`du ${1}/$NAMEPUPSFS | cut -f 1`
  SIZEPUPSFSK=`expr $SIZEPUPSFSK + 1000` #some slack.
  SIZETESTK=`expr $SIZEPUPSFSK + 1000` #more slack.
  [ "$PMEDIA" = "ideflash" ] && SIZETESTK=$SIZEFILLK #do not want pup_xxx.sfs in ram.
  if [ $SIZEFILLK -gt $SIZETESTK ];then
   #create a separate tmpfs... (thanks to Mitch for suggestion)
   echo -n "Creating tmpfs for $NAMEPUPSFS on (/initrd)/mnt/tmpfs..." >/dev/console
   mount tmpfs /mnt/tmpfs -t tmpfs -o size=${SIZEPUPSFSK}k;check_status $?
   echo -n "Copying $NAMEPUPSFS to tmpfs..." >/dev/console
   cp -f ${sfsmntpt}/$NAMEPUPSFS /mnt/tmpfs/
   sync
   losetup /dev/loop0 /mnt/tmpfs/$NAMEPUPSFS
   #do not unmount PDEV1 if mounted directly in a unionfs layer...
   [ ${1} = "/mnt/dev_ro1" ] && umntfunc /mnt/dev_ro1
   SIZEFILLK=`expr $SIZEFILLK - $SIZEPUPSFSK`
  else
   echo -n "Mntg $NAMEPUPSFS off /dev/${sfspart}..." >/dev/console
   losetup /dev/loop0 ${sfsmntpt}/$NAMEPUPSFS
  fi
  echo -n " mounting on (/initrd)/pup_ro2..." >/dev/console #mntg $NAMEPUPSFS
  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2;check_status $?
} #end loadpupsfsfunc

loadpupsavefunc() {
 #loads pup_save.3fs onto $EFSMNT
 SMNTPT="`mount | grep "/dev/$SAVEPART" | tr -s " " | cut -f 3 -d " "`"
 #v2.12 latest ntfs-3g driver does not need this...
 #[ "/dev/$SAVEPART" = "$NTFSDEV" ] && SMNPT="`mount | grep '/dev/fuse' | cut -f 3 -d ' '`"
 if [ "$SMNTPT" = "" ];then
  SMNTPT="/mnt/dev_save"
  mntfunc -t $SAVEFS -o noatime,rw /dev/$SAVEPART /mnt/dev_save
 fi
 #Kirk's encryption code, modified by Dougal..
 if [ "$CRYPTO" != "" ] ; then
  esavefile="`echo -n "$SAVEFILE" | sed -e 's/^\///g'`"
  echo "" >/dev/console
  echo -e "\\033[1;36m" >/dev/console #aqua-blue
  echo "Loading encrypted ${esavefile}..." >/dev/console
  while true; do
   echo -n "Password: " >/dev/console
   #$PUPFILESDIR/bin/losetup-FULL $CRYPTO /dev/loop1 $SMNTPT$SAVEFILE
   losetup $CRYPTO /dev/loop1 $SMNTPT$SAVEFILE
   #forum feedback this takes to long when encrypted...
   #[ ! "`echo -n "$SAVEFILE" | grep '\.2fs'`" = "" ] && $PUPFILESDIR/sbin/e2fsck -y -f /dev/loop1
   mount -t ext2 -o noatime,rw /dev/loop1 $EFSMNT
   if [ "$?" = "0" ] ; then
    break
   else 
    #$PUPFILESDIR/bin/losetup-FULL -d /dev/loop1
    losetup -d /dev/loop1
    echo "Can't mount file, try password again..." >/dev/console
   fi
  done
  echo -en "\\033[0;39m" >/dev/console
 else
  #about to mount pup_save.3fs, but before that check if need to resize it...
  if [ -f $SMNTPT/pupsaveresize.txt ];then #created by /usr/sbin/resizepfile.sh
   KILOBIG=`cat $SMNTPT/pupsaveresize.txt`
   rm -f $SMNTPT/pupsaveresize.txt
   echo -n "Increasing $SAVEFILE by $KILOBIG Kbytes, please wait..." >/dev/console
   dd if=/dev/zero bs=1024 count=$KILOBIG >> $SMNTPT$SAVEFILE
   sync
   #v2.13 see above  e2fsck -y -f $SMNTPT$SAVEFILE
   $PUPFILESDIR/sbin/e2fsck -y -f $SMNTPT$SAVEFILE #in case ext3.
   $PUPFILESDIR/sbin/resize2fs -pf $SMNTPT$SAVEFILE;check_status $? #no size, will fill all of file.
   sync
   sleep 6 #so we can see result. v2.11 only see result in log file.
   check_status 0 #v2.11 e2fsck gives an error even though it works.
  fi
  losetup /dev/loop1 $SMNTPT$SAVEFILE
  FILEFS="ext3"
  if [ ! "`echo -n "$SAVEFILE" | grep '\.2fs'`" = "" ];then
   $PUPFILESDIR/sbin/e2fsck -y -f /dev/loop1
   FILEFS="ext2"
  fi
  echo -n "Mounting ${SAVEFILE} on ${EFSMNT}..." >/dev/console
  mount -t $FILEFS -o noatime,rw /dev/loop1 $EFSMNT;check_status $?
 fi
} #end loadpupsavefunc

searchsavefunc() { #v2.15 modified.
 #this func will look in standard places for PUPSAVE file.
 [ "$PRAMONLY" ] && return #boot menu option, run totally in ram.
 echo -n "Looking for pup_save.2fs in" >/dev/console
 PUPFOUND=""
 for TESTONE in $PCPARTS
 do
  PARTDEV="`echo -n "$TESTONE" | cut -f 1 -d '|'`"
  PARTFS="`echo -n "$TESTONE" | cut -f 2 -d '|'`"
  #echo -n " ${PARTDEV}..." >/dev/console
  FULLPARTDEV="/dev/$PARTDEV "
  [ "`mount | grep "$FULLPARTDEV"`" != "" ] && continue #precaution.
  #echo "searchsavefunc: mntfunc -t $PARTFS /dev/$PARTDEV /mnt/data" #TEST
  #echo "/mnt/data already mounted? --> `mount | grep '/mnt/data'`"  #TEST
  mntfunc -t $PARTFS /dev/$PARTDEV /mnt/data
  if [ $? -eq 0 ];then
   record_fnd_func $PARTFS $PARTDEV /mnt/data #test exist pup_save*.,3fs.
   umntfunc /mnt/data
   analyse_pupfound_func save #set PUPSAVE if it exists.
   [ "$PUPSAVE" ] && break
  fi
 done
 #will only allow save session to floppy on non-usb computers...
 #checkout usb storage...
 if [ ! "$PUPSAVE" ];then
  #load usb-storage driver also...
  if [ ! "$USB" = "" ];then
   #if usb-storage.ko already loaded, then already searched above...
   if [ "`lsmod | grep "^usb_storage"`" = "" ];then
    usbstoragefunc #loads usb-storage.ko
    sleep 2 #1 v2.11 '1' fixed some PCs but not all, try '2'.
    TIMEOUTUSB=8 #dont hang around waiting in usbstoragecompletionfunc very long.
    [ "$WAITUSB" = "yes" ] && usbstoragecompletionfunc #v2.10
    SDPARTS="`probepart -k 2> /dev/null | grep '^/dev/sd' | grep -E 'ext2|ext3|reiserfs|msdos|vfat|minix|ntfs' | cut -f 1-2 -d '|' | sed -e 's/\/dev\///g' | tr "\n" " "`"
    for TESTONE in $SDPARTS
    do
     PARTDEV="`echo -n "$TESTONE" | cut -f 1 -d '|'`"
     PARTFS="`echo -n "$TESTONE" | cut -f 2 -d '|'`"
     [ ! "$SATADRIVES" = "" ] && [ ! "`echo "$SATADRIVES" | grep "$PARTDEV"`" = "" ] && continue
     echo -n " ${PARTDEV}..." >/dev/console
     mntfunc -t $PARTFS /dev/$PARTDEV /mnt/data
     if [ $? -eq 0 ];then
      record_fnd_func $PARTFS $PARTDEV /mnt/data #test exist pup_save*.,3fs.
      umntfunc /mnt/data
      analyse_pupfound_func save #set PUPSAVE if it exists.
      [ "$PUPSAVE" ] && break
     fi
    done
   fi
  else
   #non-usb computer, so check floppy drive...
   #dmesg only tells us the motherboard has floppy controller chip, I think...
   if [ ! "`dmesg | grep "Floppy drive" | grep "fd0"`" = "" ];then
    if [ ! "`disktype /dev/fd0 | grep "file system" | grep '^FAT'`" = "" ];then
     echo -n " fd0..." >/dev/console
     mount -t msdos /dev/fd0 /mnt/data
     if [ $? -eq 0 ];then
      [ -f /mnt/data/pup_save.2fs ] && PUPSAVE="vfat,fd0,/pup_save.2fs"
      umount /dev/fd0
     fi
    fi
   fi
  fi
 fi
 check_status 0
} #end searchsavefunc

#v2.15 switch_root clobbers swap partition. Rob Landley suggests this quick and dirty hack...
mount -t tmpfs -o size=50k tmpfs /dev
cp -a /dev0/* /dev
#...later on, this tmpfs gets moved to /initrd/dev in the main f.s. 

# Mount /proc:
mount -t proc none /proc
#mount -t ext2 -o remount,rw /dev/ram0 / #-n option not needed with busybox mount.

PUPPYVERSION=`cat /PUPPYVERSION`

clear #v2.11 got this out of embutils, compiled in t2 (as not currently in busybox)

echo -e "\\033[1;36m" #34=blue, 33=yellow, 32=green, 31=red, 35=purple, 36=aquablue, 38=black.
echo "Detailed bootup messages are logged to:"
echo "/tmp/bootkernel.log, /initrd/tmp/bootinit.log, /tmp/sysinit.log"
echo "Detailed ongoing messages are logged to:"
echo "/tmp/xerrs.log (X) and /var/log/messages (kernel)"
echo -e "\\033[0;39m"

echo -en "\\033[1;35m"
echo -n "Now executing 'init' script in initial-ramdisk..."
echo -e "\\033[0;39m"
echo "(Note: initial-ramdisk is retained and in /initrd after bootup)"

#v2.16 maybe already mounted rw?...
# mount -t ext2 -o remount,rw /dev/ram0 /
mount -t rootfs -o remount,rw rootfs /

#v2.16 dougal suggestion...
if [ "$DEBUG" != "yes" ];then
 exec 1>/tmp/bootinit.log 2>&1
fi

####LOAD MODULES###########################################
# Load kernel modules:
echo -n "Loading kernel modules..." >/dev/console #AAA

#base module for scsi (and usb)...
[ -f /modules/${KERNVER}/scsi_mod.ko.gz ] && zcat /modules/${KERNVER}/scsi_mod.ko.gz | insmod -
#[ -f /modules/${KERNVER}/scsi_mod.ko ] && gunzip -c /modules/${KERNVER}/scsi_mod.ko.gz | insmod -
#...builtin to my 2.6.18.1, but leave this line for other kernels.

#v2.02 pakt, forum t=8913...
#if boot option 'usbcard' then load PCMCIA modules now
#this will allow booting from USB flash pen through USB2 adapter card
if [ "$USBCARD" = "yes" ];then
 zcat /modules/${KERNVER}/pcmcia/rsrc_nonstatic.ko.gz | insmod -
 zcat /modules/${KERNVER}/pcmcia/yenta_socket.ko.gz | insmod -
 echo "Detecting USB2 adapter card..."
 sleep 2
fi

#always load this...
[ -f /modules/${KERNVER}/sd_mod.ko.gz ] && zcat /modules/${KERNVER}/sd_mod.ko.gz | insmod -
#...builtin to my 2.6.18.1, but leave this line for other kernels.
#   "sd" means scsi disk support. i think a correct sequence is
#   scsi_mod usbcore usb_uhci/ohci usb-storage sd_mod
#   ...but i think those last two can be swapped.
#   Or, if want to support a real scsi drive, sequence is
#   scsi_mod sr_mod sd_mod
#   ...those last two any order, "sr" support for cdrom.

#have not loaded usb-storage module, so any /dev/sd[a-z] drive will be sata...
#note, libata (sata) support is built into kernel.
#SATADRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"
#...no, want to delay this a bit, maybe not necessary, but have delayed...

#v2.15 moved up before usb loading...
zcat /modules/${KERNVER}/cdrom.ko.gz | insmod -    #before ide-cd.
zcat /modules/${KERNVER}/ide-cd.ko.gz | insmod -
#booting from a real scsi cd?...
#if [ "$PMEDIA" = "scsicd" -o "$PMEDIA" = "cd" ];then
 zcat /modules/${KERNVER}/sr_mod.ko.gz | insmod -
#fi
#v2.15 now allow PMEDIA=cd, find out whether it is a ide, usb or sata cd...
#make a gross assumption that PC only has one type of cd drive...
if [ "$PMEDIA" = "cd" ];then
 PMEDIA='usbcd'
 [ ! "`test-eide | grep ' cdrom '`" = "" ] && PMEDIA='idecd'
 #[ ! "`test-scsi | grep ' cdrom '`" = "" ] && PMEDIA='scsicd'
 [ ! "`test-scsi | grep '/scd'`" = "" ] && PMEDIA='satacd'
fi


#v2.10 new code using jesse's elspci...
USB="" ; MODUSB=""
[ ! "`elspci -l | grep '0C0300'`" = "" ] && MODUSB="$MODUSB uhci"
[ ! "`elspci -l | grep '0C0310'`" = "" ] && MODUSB="$MODUSB ohci"
[ ! "`elspci -l | grep '0C0320'`" = "" ] && MODUSB="$MODUSB ehci"
if [ ! "$MODUSB" = "" -o "$USBCARD" = "yes" ];then
 zcat /modules/${KERNVER}/usb/usbcore.ko.gz | insmod - 2>/dev/null
 if [ $? -eq 0 ];then
  sleep 1
  for ONE in $MODUSB
  do
   zcat /modules/${KERNVER}/usb/$ONE-hcd.ko.gz | insmod - && USB="1"
   [ "$USB" = "1" ] && [ "$ONE" = "ehci" ] && USB="2"
  done
  if [ ! "$USB" = "" ];then 
   #want usb-storage to load for every case other than these...
   if [ "`echo -n "$PMEDIA" | grep -E "ide|sata|scsi"`" = "" ];then
    #booting off a usb drive...
    usbstoragefunc #loads usb-storage.ko
    #note, usbstoragecompletionfunc gets called further down.
   fi
   #...note, in case of booting off a cd, searchsavefunc() loads usb-storage.ko, but only
   #   if cannot find pup_save.3fs in h.d.
   mount -t usbfs none /proc/bus/usb #v2.15
  fi
 fi
fi


#ide zip or ide ls-120 drive?...
[ ! "`dmesg | grep "ATAPI FLOPPY"`" = "" ] && zcat /modules/${KERNVER}/ide-floppy.ko.gz | insmod -

#a bit further down complains needs nls_cp437 and nls_iso8859-1.
#(these are default chars sets for win/linux filesystems, specified in kernel config)
zcat /modules/${KERNVER}/nls_cp437.ko.gz | insmod -
zcat /modules/${KERNVER}/nls_iso8859-1.ko.gz | insmod -

#filesystems...
[ -f /modules/${KERNVER}/reiserfs.ko.gz ] && zcat /modules/${KERNVER}/reiserfs.ko.gz | insmod -
[ -f /modules/${KERNVER}/ntfs.ko.gz ] && zcat /modules/${KERNVER}/ntfs.ko.gz | insmod -
#...my 2.6.18.1 has reiserfs and ntfs builtin, leave these lines for other kernels.
if [ $aufs ];then #v2.16rc
 zcat /modules/${KERNVER}/aufs.ko.gz | insmod -
else
 zcat /modules/${KERNVER}/unionfs.ko.gz | insmod -
fi
#v2.02 for ntfs-3g driver...
zcat /modules/${KERNVER}/fuse.ko.gz | insmod -

#delayed this... have this line in usbstoragefunc, but if that func does
#not execute, do it here...
[ ! "$WAITUSB" = "yes" ] && SATADRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"

#v2.15 analyse_pupfound_func may require choosing from multiple pup_save files,
#ps/2 keyboard support builtin to kernel, but not usb keyboard (code from pakt)...
if [ "$USB" != "" ];then
 [ ! -e /proc/bus/usb/devices ] && sleep 1
 #sleep 1
 cat /proc/bus/usb/devices > /tmp/usbdevices.log
 if [ ! "`cat /proc/bus/usb/devices | grep "Cls=03(HID  ) Sub=01 Prot=01"`" = "" ];then
  zcat /modules/${KERNVER}/usb/usbhid.ko.gz | insmod -
 fi
fi

#v2.10 jesse's second part of usbstoragefunc...
[ "$WAITUSB" = "yes" ] && usbstoragecompletionfunc
check_status 0 #v2.11 AAA

#note: aes and cryptoloop modules may be loaded in loadpupsavefunc.
###########################################################

#locate all partitions...
PCPARTSALL="`probepart -k 2> /dev/null`"
PCPARTS0="`echo "$PCPARTSALL" | grep '^/dev/' | cut -f 1-2 -d '|'  | grep -E 'iso9660|ext2|ext3|reiserfs|msdos|vfat|minix|ntfs' | sed -e 's/\/dev\///g'`"
PCPARTS="`echo "$PCPARTS0" | tr "\n" " "`" #note, will have a space char on end.

#a problem is that sata and usb drives both have /dev/sd names...
USBDRIVES=""
ALLSD="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr '\n' ' '`"
if [ ! "$SATADRIVES" = "" ];then
 for ONESD in $ALLSD
 do
  [ "`echo "$SATADRIVES" | grep "$ONESD" `" = "" ] && USBDRIVES="$USBDRIVES $ONESD"
 done
else
 USBDRIVES="$ALLSD"
fi
#Note: USBDRIVES & SATADRIVES excludes CD/DVD drives.

IDEDRIVES="`test-eide | grep '\- disk \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
#Note: IDEDRIVES excludes CD/DVD, zip drives.

#find any zip drives...
ZIPDRIVES="`test-eide | grep '\- floppy \-' | cut -f 1 -d " " | cut -f 3 -d "/" | head -n 1`"
#...singular, just find one drive.
#PCPARTS problem, probepart does not report zip/ls120 partitions...
if [ "$ZIPDRIVES" ];then
 INFOZIP="`disktype /dev/$ZIPDRIVES | tr -s " "`"
 ZIPNUM="`echo "$INFOZIP" | grep '^Partition ' | cut -f 1 -d ':' | cut -f 2 -d " " | head -n 1`"
 if [ "`echo "$INFOZIP" | grep 'file system' | head -n 1 | grep '^ '`" = "" ];then
  FSZIP="`echo "$INFOZIP" | grep 'file system' | cut -f 1 -d " " | head -n 1`"
 else
  FSZIP="`echo "$INFOZIP" | grep 'file system' | cut -f 2 -d " " | head -n 1`"
 fi
 fsfunc $FSZIP #ex: FAT16, will return vfat.
 FSZIP="$FSTYPE"
 PCPARTS0="${PCPARTS0}
${ZIPDRIVES}${ZIPNUM}|${FSZIP}"
 #note, PCPARTS has a space char on the end...
 PCPARTS="${PCPARTS}${ZIPDRIVES}${ZIPNUM}|${FSZIP} "
fi


PDEV1=""
case $PMEDIA in
 idecd)
  IDECDS="`test-eide | grep '\- cdrom \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
  search_drives_func $IDECDS
  #...ex, sets: PDEV1=hdc FSTYPE=iso9660 PUPSFS=iso9660,hdc,pup_001.sfs PUPSAVE=vfat,hda1,/pup_save.2fs
  [ ! "$PUPSAVE" ] && searchsavefunc #search further for PUPSAVE.
  ;;
 idehd)
  search_drives_func $IDEDRIVES
  #...return with PDEV1=hda3 FSTYPE=ext3 PUPSFS=ext3,hda3,pup_215.sfs (for example)
  ;;
 usbflash)
  search_drives_func $USBDRIVES
  ;;
 ideflash)
  #this looks like a normal ide drive. Note, may require boot param "ide=nodma"
  search_drives_func $IDEDRIVES
  ;;
 idezip)
  search_drives_func $ZIPDRIVES
  ;;
 satahd)
  search_drives_func $SATADRIVES
  ;;
 usbhd)
  ##USBDRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"
  search_drives_func $USBDRIVES
  ;;
 usbcd|satacd|scsicd)
  #v2.15 usb|sata cd drives are /dev/scd[0-9]...
  SCSICDS="`echo -n "$PCPARTS0" | grep '^scd' | cut -b 1-4 | tr '\n' ' '`"
  #SCSICDS="`test-scsi | grep '\- cdrom \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
  search_drives_func $SCSICDS
  [ ! "$PUPSAVE" ] && searchsavefunc #search further for PUPSAVE.
  ;;
 scsihd) #TODO
  echo "scsihd todo"
  ;;
 *) #ransack the entire PC looking for puppy!
  ALLDRIVES="`probedisk 2> /dev/null | grep '^/dev/' | cut -f 1 -d '|' | cut -f 3 -d '/' | tr "\n" " "`"
  search_drives_func $ALLDRIVES
  [ ! "$PMEDIA" ] && guesspmediafunc
  [ ! "$PUPSAVE" ] && searchsavefunc #search further for PUPSAVE.
  ;;
esac
#...exit with PDEV1= boot device name.

#total ram, less any shared video...
PCRAMSIZE=`free | head -n 2 | tail -n 1 | tr -s " " | cut -f 3 -d " "`
SIZEFILLK=`expr $PCRAMSIZE \/ 2` #half of ram.
#for 128M PC, have to tweak this to get pup_xxx.sfs to load into ram...
if [ $SIZEFILLK -gt 50000 ];then
 #v2.15 going back to this first one... do not load pup_xxx.sfs into ram for 128M PCs (with no swap)...
 [ $SIZEFILLK -lt 70000 ] && SIZEFILLK=71680 #70M.
 #[ $SIZEFILLK -lt 74752 ] && SIZEFILLK=74752 #73M. 3may06 pushing the limit here.
 #[ $SIZEFILLK -lt 77824 ] && SIZEFILLK=77824 #76M. 10may06 pushing the limit a bit more. v2.14-
 #...see below, hack this a bit more for 128M PCs.
fi
#teddog wants this, more space for loading multisession folders...
if [ $PCRAMSIZE -gt 450000 ];then #pc has 512M RAM.
 QTRFILLK=`expr $PCRAMSIZE \/ 4` #quarter of ram.
 SIZEFILLK=`expr $SIZEFILLK + $QTRFILLK`
fi
PHYSICALFILLK="$SIZEFILLK"

#want to know if there is a swap partition available...
SWAPSIZE=0
#SWAPINFO="`fdisk -l | grep "Linux swap" | head -n 1`"
SWAPINFO="`echo "$PCPARTSALL" | grep 'Linux Swap' | head -n 1`"
if [ ! "$SWAPINFO" = "" ];then
 #we can make the ramdisk real big now...
 SWAPPART="`echo "$SWAPINFO" | cut -f 1 -d "|"`"
 SWAPSIZE=`echo -n "$SWAPINFO" | cut -f 3 -d '|'` #`fdisk -s $SWAPPART`
 SWAPSIZ4=`expr $SWAPSIZE \/ 4`
 SWAPSIZ2=`expr $SWAPSIZE \/ 2`
 SWAPSIZE=`expr $SWAPSIZ2 + $SWAPSIZ4` #3/4 of original
 SIZEFILLK=`expr $SIZEFILLK + $SWAPSIZE`
 echo -n "Loading swap partition $SWAPPART..." >/dev/console
 swapon $SWAPPART;check_status $?
fi

##puppy is getting too fat for 128M PCs...
#if [ $SIZEFILLK -eq 77824 ];then #this exact size, see above.
# #case of 128M PC and no swap partition.
# #pup_xxx.sfs is 68M, only allow a slimmer pup to load into ram...
# SIZEFILLK=69632 #68M
#fi
#...had this in v2.00 standard, taking out for operatic-2.00, 2.01.

if [ "$PUPSAVE" ];then
 SAVEFS="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"   #f.s. and partition where pup_save.3fs is located.
 [ "$SAVEFS" = "msdos" ] && SAVEFS="vfat" #7apr06 think i can do this.
 SAVEPART="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
 SAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
fi

#decide on an appropriate PUPMODE...
PUPMODE=1                                              #using tmpfs.
[ "$DEV1PUP" = "yes" ] && PUPMODE=`expr $PUPMODE + 2`  #PDEV1 has full h.d. puppy installation.
[ "$PUPSFS" ] && PUPMODE=`expr $PUPMODE + 4`           #pup_xxx.sfs exists.
[ "$PUPSAVE" ] && PUPMODE=`expr $PUPMODE + 8`          #pup_save.3fs exists.
if [ $PUPMODE -eq 13 ];then
 #pup_save.2fs is on a fast media, allows unlimited writes, so let us not use tmpfs layer...
 [ ! "`echo -n "$PMEDIA" | grep -E "idehd|satahd|scsihd"`" = "" ] && PUPMODE=12
 if [ ! "`echo -n "$PMEDIA" | grep -E "idecd|usbcd|scsicd"`" = "" ];then
  #booting off a cd. if pup_save.3fs exists in a fast media, can load direct...
  [ ! "`echo -n "$SAVEPART" | grep '^hd'`" = "" ] && PUPMODE=12
  #also detect if on sata drive...
  SAVEDRV="`echo -n "$SAVEPART" | cut -b 1-3`"
  [ ! "`echo -n "$SATADRIVES" | grep "$SAVEDRV"`" = "" ] && PUPMODE=12
 fi
 #multisession cd, run in PUPMODE 13+64=77
 [ ! "`echo -n "$PUPSAVE" | grep '/20[0-9][0-9]'`" = "" ] && PUPMODE=77  
fi
if [ $PUPMODE -eq 7 ];then
 #PDEV1 has puppy installed (or sessions saved direct to partition) and pup_xxx.sfs, but do
 #not use a tmpfs layer if PDEV1 is fast media...
 [ ! "`echo -n "$PMEDIA" | grep -E "idehd|satahd|scsihd"`" = "" ] && PUPMODE=6
fi

#mount the main puppy f.s....
NEWFILESMNTPT="/pup_ro2"
[ "$PUPFILESDIR" ] && NEWFILESMNTPT="$PUPFILESDIR" #v2.15
OLDFILESMNTPT=""
UMNT1='/pup_rw=rw'
DEV1MNT="/pup_ro1"
case $PUPMODE in
 3) #PDEV1 has puppy, and using tmpfs (maybe).
  #we could leave usbhd out of this, as it is slow...
  if [ ! "`echo -n "$PMEDIA" | grep -E "usbhd|idehd|satahd|scsihd"`" = "" ];then
   #do not use unionfs at all, just mount on /pup_new instead of /pup_rw...
   echo -n "Mounting /dev/${PDEV1} on /pup_new (becomes '/')..." >/dev/console
   mntfunc -o rw -t $FSTYPE /dev/$PDEV1 /pup_new;check_status $?
   PUPMODE=2
  else
   echo -n "Mounting /dev/${PDEV1} on (/initrd)/pup_ro1..." >/dev/console
   mntfunc -o ro -t $FSTYPE /dev/$PDEV1 /pup_ro1;check_status $?
   echo -n "Mounting tmpfs on (/initrd)/pup_rw..." >/dev/console
   mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k;check_status $?
   UMNT1='/pup_rw=rw:/pup_ro1=ro'
  fi
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  ;;
 5) #tmpfs, no persistent storage layer, pup_xxx.sfs
  #this will be the case for first boot. ***FIRST BOOT SITUATION***
  echo -n "Mounting /dev/${PDEV1} on (/initrd)/mnt/dev_ro1..." >/dev/console
  mntfunc -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1;check_status $?
  loadpupsfsfunc /mnt/dev_ro1 #loads pup_xxx.sfs (in PDEV1 partition) to /pup_ro2
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  echo -n "Mounting tmpfs on (/initrd)/pup_rw..." >/dev/console
  mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k;check_status $?
  UMNT1='/pup_rw=rw:/pup_ro2=ro'
  ;;
 6) #PDEV1 is persistent storage top layer, pup_xxx.sfs.
  #similar to mode 12, except a partition is mounted direct on top layer.
  echo -n "Mounting /dev/${PDEV1} on (/initrd)/pup_rw..." >/dev/console
  mntfunc -o rw -t $FSTYPE /dev/$PDEV1 /pup_rw;check_status $?
  loadpupsfsfunc /pup_rw #loads pup_xxx.sfs (in PDEV1 partition) to /pup_ro2
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  UMNT1='/pup_rw=rw:/pup_ro2=ro'
  OLDFILESMNTPT="/pup_rw"
  ;;
 7) #tmpfs, PDEV1 is persistent storage, pup_xxx.sfs.
  echo -n "Mounting /dev/${PDEV1} on (/initrd)/pup_ro1..." >/dev/console
  mntfunc -o rw -t $FSTYPE /dev/$PDEV1 /pup_ro1;check_status $?
  loadpupsfsfunc /pup_ro1 #loads pup_xxx.sfs (in PDEV1 partition) to /pup_ro2
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  echo -n "Mounting tmpfs on (/initrd)/pup_rw..." >/dev/console
  mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k;check_status $?
  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
  OLDFILESMNTPT="/pup_ro1"
  ;;
 12) #pup_save.3fs is persistent storage top layer, pup_xxx.sfs.
  #booting from cd is special case. if pup_xxx.sfs was found in same place as 
  #pup_save.3fs use that instead...
  [ "`echo -n "$PMEDIA" | grep 'cd$'`" = "" ] && XTRAPUPSFS=""
  if [ ! "$XTRAPUPSFS" = "" ];then
   echo -n "Mounting /dev/$SAVEPART on (/initrd)/mnt/dev_save..." >/dev/console
   mntfunc -t $SAVEFS -o noatime,rw /dev/$SAVEPART /mnt/dev_save;check_status $?
   echo -n "Mntg $NAMEPUPSFS directly off /dev/$SAVEPART onto (/initrd)/pup_ro2..." >/dev/console
   losetup /dev/loop0 /mnt/dev_save/$NAMEPUPSFS
   mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2;check_status $?
  else
   echo -n "Mounting /dev/${PDEV1} on (/initrd)/mnt/dev_ro1..." >/dev/console
   mntfunc -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1;check_status $?
   loadpupsfsfunc /mnt/dev_ro1 #loads pup_xxx.sfs (in PDEV1 partition) to /pup_ro2
  fi
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  #pup_save.sfs is on a fast media, allows unlimited writes, so let us not use tmpfs layer...
  EFSMNT="/pup_rw"      #pup_save.3fs top layer.
  loadpupsavefunc #loads pup_save.3fs onto EFSMNT
  UMNT1='/pup_rw=rw:/pup_ro2=ro'
  OLDFILESMNTPT="/pup_rw"
  ;;
 13) #tmpfs, pup_save.3fs is persistent storage, pup_xxx.sfs.
  echo -n "Mounting /dev/${PDEV1} on (/initrd)/mnt/dev_ro1..." >/dev/console
  mntfunc -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1;check_status $?
  loadpupsfsfunc /mnt/dev_ro1 #loads pup_xxx.sfs (in PDEV1 partition) to /pup_ro2
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  EFSMNT="/pup_ro1"  #pup_save.3fs next layer.
  loadpupsavefunc #loads pup_save.3fs onto EFSMNT
  echo -n "Mounting tmpfs on (/initrd)/pup_rw..." >/dev/console
  mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k;check_status $?
  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
  OLDFILESMNTPT="/pup_ro1"
  ;;
 77) #multisession cd/dvd
  SAVEFS="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"   #f.s. and partition where pup_save.3fs is located.
  SAVEPART="`echo -n "$PUPSAVE" | cut -f 2 -d ','`" # "
  SAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
  #echo -n "Mounting /dev/${PDEV1} on (/initrd)/mnt/dev_ro1..." >/dev/console
  mount -o noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1 #;check_status $?
  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
  #now do PUPSAVE...
  SMNTPT="`mount | grep "/dev/$SAVEPART" | tr -s " " | cut -f 3 -d " "`"
  if [ "$SMNTPT" = "" ];then
   SMNTPT="/mnt/dev_save"
   mount -t $SAVEFS -o noatime /dev/$SAVEPART /mnt/dev_save
  fi
  #personal data is saved in dated folders.
  #create a tmpfs on /pup_ro1 and load folders to it... in physical mem only...
  ALMOSTFILLK=`expr $PHYSICALFILLK \/ 4`
  ALMOSTFILLK=`expr $PHYSICALFILLK - $ALMOSTFILLK`
  #echo -n "Mounting a tmpfs on (/initrd)/pup_ro1..." >/dev/console
  mount tmpfs /pup_ro1 -t tmpfs -o size=${ALMOSTFILLK}k #;check_status $?
  loadfolders $SMNTPT /pup_ro1
  ALMOSTFILLK=`free | grep 'Mem:' | tr -s " " | cut -f 5 -d " "`
  ALMOSTFILLK=`expr $ALMOSTFILLK \/ 2`
  SIZEFILLK=`expr $ALMOSTFILLK + $SWAPSIZE`
  
  #v2.16 need separate tmpfs for the pup_xxx.sfs file...
  RWSIZEK=$SIZEFILLK #tmpfs space to allocate for the pup_rw layer.
  RO2SIZEK=0         #tmpfs space to allocate for the pup_ro2 (to hold pup_xxx.sfs) layer.
  SIZEPUPSFSK=`du /mnt/dev_ro1/$NAMEPUPSFS | cut -f 1`
  if [ $SIZEFILLK -gt `expr $SIZEPUPSFSK \* 2` ];then
   RWSIZEK=`expr $SIZEFILLK - $SIZEPUPSFSK` #allocate at least same size as pup_xxx.sfs file.
   RO2SIZEK=`expr $SIZEPUPSFSK + 500` #500 is slack space.
  fi
  
  echo -n "Mounting tmpfs on (/initrd)/pup_rw..." >/dev/console
  mount tmpfs /pup_rw -t tmpfs -o size=${RWSIZEK}k;check_status $?
  
  #v2.16 comment-out, rethink this.... maybe handled later?...
  ##if loading extra .sfs files off the cd, must have a linux swap part...
  #if [ ! "$MORE1SFS" = "" ];then
  # if [ "$SWAPPART" = "" ];then
  #  echo "WARNING: Cannot load $MORE1SFS as no swap partition" >/dev/console
  #  sleep 10
  # else
  #  for ONEMORE in $MORE1SFS
  #  do
  #   echo "Copying $ONEMORE from CD/DVD..." >/dev/console
  #   cp -f /mnt/dev_ro1/$ONEMORE /pup_rw/
  #   sync
  #  done
  # fi
  #fi
  
  #if enough room in ramdisk, copy it... v2.16 modified...
  if [ $RO2SIZEK -gt 0 ];then
   echo -n "Copying $NAMEPUPSFS to ramdisk and mount on (/initrd)/pup_ro2..." >/dev/console
   mount tmpfs /mnt/tmpfs -t tmpfs -o size=${RO2SIZEK}k
   cp -f /mnt/dev_ro1/$NAMEPUPSFS /mnt/tmpfs/
   sync
   losetup /dev/loop0 /mnt/tmpfs/$NAMEPUPSFS
   umount /dev/$PDEV1 #/mnt/dev_ro1
  else
   echo -n "Mounting $PUPSFS directly off /dev/$PDEV1 onto (/initrd)/pup_ro2..." >/dev/console
   losetup /dev/loop0 /mnt/dev_ro1/$NAMEPUPSFS
  fi
  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2;check_status $?
  sync
  umount /dev/$SAVEPART 2>/dev/null
  OLDFILESMNTPT="/pup_ro1"
  enable_all_execs #/usr, /lib links to the main puppy filesystem, in dir $PUPFILESDIR
  ;;
 *) #incomplete combination.
  #nothing to save to and/or no puppy found.
  echo -e "\\033[1;31m" >/dev/console #34=blue, 33=yellow, 32=green, 31=red, 35=purple, 36=aquablue, 38=black.
  echo "ERROR, cannot find Puppy on '$PMEDIA' boot media." >/dev/console
  echo "PUPMODE=$PUPMODE  PDEV1=$PDEV1" >/dev/console
  echo "Exited to initial-ramdisk (initramfs) commandline..." >/dev/console
  echo "(the Linux-guru can now debug, 'e3' editor is available)" >/dev/console
  echo -e "\\033[0;39m" >/dev/console
  exec /bin/sh >/dev/console 2>&1 #exit
  ;;
esac

#no, doing this in rc.shutdown...
##v2.16 now supporting writable compressed ext2 f.s...
#if [ "$OLDFILESMNTPT" != "" ];then
# if [ "`echo "$PUPSAVE" | grep '\.2fs'`" != "" ];then
#  if [ ! -d $OLDFILESMNTPT/usr ];then
#   #set compressed attribute on directory... only if kernel has e2compr patch...
#   if [ "`dmesg | grep 'e2compr'`" != "" ];then
#    mkdir -p $OLDFILESMNTPT/usr
#    mkdir -p $OLDFILESMNTPT/opt
#    mkdir -p $OLDFILESMNTPT/root
#    mkdir -p $OLDFILESMNTPT/lib
#    #note, chattr is from e2fsprogs, patched with e2compr, dietlibc static...
#    chattr +c $OLDFILESMNTPT/usr
#    chattr +c $OLDFILESMNTPT/opt
#    chattr +c $OLDFILESMNTPT/root
#    chattr +c $OLDFILESMNTPT/lib
#   fi
#  fi
# fi
#fi

#v2.16 user boot configuration...
mkdir -p /pup_rw/etc/rc.d
#older pup_save.2fs <v2.16 will not have this file...
[ ! -f $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG ] && touch $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG
#note, OLDFILESMNTPT can also be "" so BOOTCONFIG needs to exist in initrd also.
. $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG
#...can have EXTRASFSLIST, to override auto-generated list below...
# (space-delimited list must only be of .sfs files located at /mnt/home, or '/' for full hd install)
#...can have UNDERDOGPART, to specify an "underdog Linux"....
EXTRASFSMODE='auto' #if no EXTRASFSLIST in BOOTCONFIG.
[ "`cat $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG | grep '^EXTRASFSLIST'`" != "" ] && EXTRASFSMODE='user'
##keeping a record of all different unionfs layer configurations...
#ALLUNIONRECORDS="`cat $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG | grep '^UNIONRECORD'`"

UMNTRO=""
#Look for *_$PUPPYVERSION.sfs (ex: dev_200.sfs)...
[ $PUPMODE -eq 7 ] && EXTRASFSMNTPT="/pup_ro1"
[ $PUPMODE -eq 12 ] && EXTRASFSMNTPT="`mount | grep "/dev/$SAVEPART " 2>/dev/null | tr -s " " | cut -f 3 -d " "`"
[ $PUPMODE -eq 13 ] && EXTRASFSMNTPT="`mount | grep "/dev/$SAVEPART " 2>/dev/null | tr -s " " | cut -f 3 -d " "`"
if [ $PUPMODE -eq 77 ];then
 #v2.16 see if cd still mounted...
 UPATTERN="/dev/$PDEV1 "
 EXTRASFSMNTPT="`mount | grep "$UPATTERN" | cut -f 3 -d ' '`"
 #otherwise, expect all sfs filese to be loaded into ram...
 [ "$EXTRASFSMNTPT" = "" ] && EXTRASFSMNTPT="`mount | grep "/pup_rw" 2>/dev/null | tr -s " " | cut -f 3 -d " "`"
fi
if [ "$EXTRASFSMNTPT" ];then
 cd $EXTRASFSMNTPT
 if [ -f underdog.lnx -o "$UNDERDOGPART" ];then #v2.16
  #this is an idea to overlay Puppy on top of an existing Linux distro.
  [ ! "$UNDERDOGPART" ] && UNDERDOGPART="`cat underdog.lnx`"
  UPATTERN="/dev/$UNDERDOGPART"
  UDMNTPT="`mount | grep "$UPATTERN" | tr -s " " | cut -f 3 -d " "`"
  if [ "$UDMNTPT" = "" ];then
   UNDERDOGFS="`disktype /dev/$UNDERDOGPART | grep 'file system' | head -n 1 | cut -f 1 -d " " | tr A-Z a-z`"
   #[ "$UNDERDOGFS" = "Ext2" ] && UNDERDOGFS="ext2"
   #[ "$UNDERDOGFS" = "Ext3" ] && UNDERDOGFS="ext3"
   #[ "$UNDERDOGFS" = "Reiserfs" ] && UNDERDOGFS="reiserfs"
   if [ ! "`echo -n "$UNDERDOGFS" | grep -E 'ext2|ext3|reiserfs'`" = "" ];then
    mount -r -t $UNDERDOGFS /dev/$UNDERDOGPART /pup_ro3
    if [ $? -eq 0 ];then
     UMNTRO="${UMNTRO}:/pup_ro3=ro"
     #fixes to prevent library clashes...
     MNTFIX='/pup_rw'
     [ ! "`echo -n "$UMNTRO" | grep 'pup_ro1'`" = "" ] && MNTFIX='/pup_ro1'
     [ ! -f $MNTFIX/lib/.wh.i686 ] && $PUPFILESDIR/bin/touch $MNTFIX/lib/.wh.i686 #hides /lib/i686
     #puppy needs dir name /usr/lib/qt at bootup (see rc.profile)...
     REALQTDIR="`find /pup_ro3/usr/lib -maxdepth 1 -type d -name qt* | tail -n 1 | sed -e 's/\/pup_ro3\/usr\/lib\///g'`"
     if [ "$REALQTDIR" ];then
      if [ ! -e $MNTFIX/usr/lib/qt ];then
       [ "`find /pup_ro3/usr/lib -maxdepth 1 -xtype d -name qt`" = "" ] && ln -s $REALQTDIR $MNTFIX/usr/lib/qt
      fi
     fi
    fi
   fi
  else
   UMNTRO="${UMNTRO}:${UDMNTPT}=ro"
  fi
 else
  CNTLOOP=3
  #v2.12 exclude all z*.sfs files (reserved for special purposes)...
  #v2.12 changed exclusion ^pup_ to just ^pup ...
  #NEWSFS=""
  if [ "$EXTRASFSLIST" ];then #v2.16
   #if the user has created a list, better make sure it's valid....
   FIXEDSFSLIST=""
   EXTRASFSLIST="`echo -n "$EXTRASFSLIST" | tr ' ' '\n' | grep -v '^z' | grep -v "^pup" | tr "\n" " "`"
   for ONESFS in $EXTRASFSLIST
   do
    #eliminate other vesions...
    [ "`echo "$ONESFS" | grep '_[0-9][0-9][0-9]' | grep -v "$PUPPYVERSION"`" != "" ] && continue
    #test it exists...
    [ "`ls -1 $ONESFS`" = "" ] && continue
    if [ "$FIXEDSFSLIST" = "" ];then
     FIXEDSFSLIST="${ONESFS}"
    else
     FIXEDSFSLIST="${FIXEDSFSLIST} ${ONESFS}"
    fi
   done
   if [ "EXTRASFSLIST" != "$FIXEDSFSLIST" ];then
    EXTRASFSLIST="$FIXEDSFSLIST"
    grep -v 'EXTRASFSLIST' $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG > /tmp/BOOTCONFIG
    cat /tmp/BOOTCONFIG > /pup_rw/etc/rc.d/BOOTCONFIG
    echo "EXTRASFSLIST='$EXTRASFSLIST'" >> /pup_rw/etc/rc.d/BOOTCONFIG
   fi
  fi
  if [ "$EXTRASFSMODE" = "auto" ];then
   EXTRASFSLIST="`ls -1 *_${PUPPYVERSION}.sfs | grep -v '^z' | grep -v "^pup" | tr "\n" " "`"
   #if [ -f $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG ];then
   # grep -v 'EXTRASFSLIST' $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG > /tmp/BOOTCONFIG
   # cat /tmp/BOOTCONFIG > /pup_rw/etc/rc.d/BOOTCONFIG
   #fi
   #echo "EXTRASFSLIST='$EXTRASFSLIST'" >> /pup_rw/etc/rc.d/BOOTCONFIG
  fi
  for ONESFS in $EXTRASFSLIST
  do
   ##v2.14 want to delete invalid "opaque" whiteout files if new layer added...
   #if [ "`$PUPFILESDIR/bin/stat --format=%a $EXTRASFSMNTPT/$ONESFS`" = "744" ];then
   # NEWSFS="${NEWSFS}/pup_ro${CNTLOOP} " #variable read further down.
   # chmod 766 $EXTRASFSMNTPT/$ONESFS #so won't set NEWSFS at next boot.
   #fi
   losetup /dev/loop${CNTLOOP} $EXTRASFSMNTPT/$ONESFS
   mount -r -t squashfs -o noatime /dev/loop${CNTLOOP} /pup_ro${CNTLOOP}
   [ $? -eq 0 ] && UMNTRO="${UMNTRO}:/pup_ro${CNTLOOP}=ro"
   CNTLOOP=`expr $CNTLOOP + 1`
   [ $CNTLOOP -eq 6 ] && break #kernel supports max 8 loop devices,
   #...but, only support adding 3 extra .sfs files, as performance degrades as each layer added.
  done
 fi
 cd /
fi


#v2.16 keep record of different layer configurations...
savenameonly="`echo "$PUPSAVE" | cut -f 2 -d '/'`"
sfsnameonly="`echo "$PUPSFS" | cut -f 2 -d '/'`"
NEWUNIONRECORD="${savenameonly} ${sfsnameonly} ${EXTRASFSLIST}"
#if current layers different from last bootup, will need to fix menus (etc)...
#
##record current layers for comparison at next bootup...
#grep -v '^LASTUNIONRECORD' $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG >/tmp/BOOTCONFIG
#cp -f /tmp/BOOTCONFIG /pup_rw/etc/rc.d/BOOTCONFIG
#echo "LASTUNIONRECORD='$NEWUNIONRECORD'" >> /pup_rw/etc/rc.d/BOOTCONFIG
##add this layer configuration if not already recorded...
#if [ "`echo "$ALLUNIONRECORDS" | grep "$NEWUNIONRECORD"`" = "" ];then
# echo "UNIONRECORD='$NEWUNIONRECORD'" >> /pup_rw/etc/rc.d/BOOTCONFIG
# echo "UNIONRECORD='$NEWUNIONRECORD'"
# echo "New unionfs layer configuration, will perform white-out file check on layers."
#else
# NEWUNIONRECORD=""
#fi
#no, do it simpler...
cat $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG | grep -v '^PREVUNIONRECORD' | sed -e 's/^LASTUNIONRECORD/PREVUNIONRECORD/g' >/pup_rw/etc/rc.d/BOOTCONFIG
sync
echo "LASTUNIONRECORD='$NEWUNIONRECORD'" >> /pup_rw/etc/rc.d/BOOTCONFIG
[ "$LASTUNIONRECORD" = "$NEWUNIONRECORD" ] && NEWUNIONRECORD="" #used below.
#...if layers changed since last boot, code further down will do whiteout files purge.
#.../etc/rc.d/rc.update reads BOOTCONFIG, updates menu (etc) if layers changed.

#after pivot_root, rc.sysinit calls rc.update, but need to do pre-cleaning...
if [ ! "$OLDFILESMNTPT" = "" ];then
 #it seems stuff can accumulate in /tmp. gets filled with unionfs whiteout files...
 echo "Cleaning out /tmp..."
 rm -rf $OLDFILESMNTPT/tmp
 mkdir $OLDFILESMNTPT/tmp
 chmod 777 $OLDFILESMNTPT/tmp
 #clean out some more temp dirs...
 rm -rf $OLDFILESMNTPT/root/tmp 2>/dev/null
 rm -f $OLDFILESMNTPT/root/.wh.tmp 2>/dev/null
 rm -rf $OLDFILESMNTPT/root/.thumbnails/* 2>/dev/null
 rm -f $OLDFILESMNTPT/root/.thumbnails/.wh.* 2>/dev/null
 if [ ! -L $OLDFILESMNTPT/usr/X11R6 ];then #test if a symlink.
  #this is supposed to be a link to X11R6. <2.10 it won't be...
  if [ -d $OLDFILESMNTPT/usr/X11R6 ];then
   mkdir -p $OLDFILESMNTPT/usr/X11R7
   cp -af $OLDFILESMNTPT/usr/X11R6/* $OLDFILESMNTPT/usr/X11R7/
   rm -rf $OLDFILESMNTPT/usr/X11R6
  fi
  ln -s X11R7 $OLDFILESMNTPT/usr/X11R6
 fi
 #now do the more drastic cleanout...
 NEWPVERSION=$PUPPYVERSION
 OLDPVERSION=`cat $OLDFILESMNTPT/etc/puppyversion 2>/dev/null`
 [ ! $OLDPVERSION ] && OLDPVERSION=$NEWPVERSION
 [ "$PCLEAN" = "yes" ] && OLDPVERSION=`expr $NEWPVERSION - 1` #v2.13
 [ "$PPURGE" = "yes" ] && OLDPVERSION=`expr $NEWPVERSION - 1`
 if [ $NEWPVERSION -gt $OLDPVERSION ];then
  echo -en "\\033[1;35m"  >/dev/console #35=purple.
  echo "Version update, restoring 'official' files, please wait..." >/dev/console
  echo -en "\\033[0;39m" >/dev/console
  echo "(with a slow CPU this may take sometime, please be patient)" >/dev/console
  #v2.16 do not overwrite rox desktop setup, as /etc/rc.d/rc.update now handles it...
  [ -f $OLDFILESMNTPT/root/Choices/ROX-Filer/PuppyPin ] && touch $OLDFILESMNTPT/root/Choices/ROX-Filer/PuppyPin
  [ -f $OLDFILESMNTPT/root/Choices/ROX-Filer/globicons ] && touch $OLDFILESMNTPT/root/Choices/ROX-Filer/globicons
  rm -f $OLDFILESMNTPT/var/log/modprobes.log 2>/dev/null #v2.13 see /sbin/modprobe script.
  #...not necessary, not using this file anymore.
  mkdir $OLDFILESMNTPT/tmp/versioncleanup
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.sysinit
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.update
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.modules
  #i think if a file exists both in OLDFILESMNTPT and in NEWFILESMNTPT, remove
  #it from OLDFILESMNTPT (as OLDFILESMNTPT is upper layer and will hide the
  #'official' file. But, only do it if 'official' file has a newer modify date...
  cd $NEWFILESMNTPT
  #find ./ -type f | sed -e 's/^\.//g' |  getting 'memory exhausted' with sed (dietlibc)
  #v2.11 Dougal suggested some improvements here...
  #find ./ -type f | grep -o '/.*' |
  #Dougal: the print0 xargs is for handling filenames with spaces...
  #find ./ -noleaf -type f -print0 | xargs -0 grep -o '/.*' |
  #ummm, no not convinced...
  #v2.12 this while-loop has become ultra-slow... seems upx compressed execs
  #responsible, recently upx-ed all the execs, now restore busybox, grep, cp.
  DOTCNT=0 #v2.12
  #v2.15 grep not support -o option...
  #find ./ -noleaf -type f | grep -o '/.*' |
  find ./ -noleaf -type f | sed -e 's/^\.//g' |
  while read ONENEW
  do
   DOTCNT=`expr $DOTCNT + 1`
   [ $DOTCNT -gt 100 ] && DOTCNT=0 #v2.12 display a dot every time cnts to 100.
   [ $DOTCNT -eq 100 ] && echo -n '*' >/dev/console #v2.12
   #note, screens out spaces also...
   [ ! "`echo -n "$ONENEW" | grep -E '^/dev|^/tmp|^/proc| '`" = "" ] && continue
   ONEBASE="`basename $OLDFILESMNTPT$ONENEW`"
   OLDDIR="`dirname $OLDFILESMNTPT$ONENEW`"
   #a whiteout file 'on top' will hide the 'official' file...
   [ -f $OLDDIR/.wh.$ONEBASE ] && rm -f $OLDDIR/.wh.$ONEBASE
   #v2.11 unionfs may create .wh.__dir_opaque, which hides all
   #contents of the directory in the lower layer ...seems to happen
   #when not required and really stuffs things up. fix...
   [ -f $OLDDIR/.wh.__dir_opaque ] && rm -f $OLDDIR/.wh.__dir_opaque
   #let's get paranoid and imagine directories also wiped...
   while [ ! "$OLDDIR" = "/" ];do
    OLDDIR="`dirname $OLDDIR`"
    UP1BASE="`basename $OLDDIR`"
    [ -f $OLDDIR/.wh.$UP1BASE ] && rm -f $OLDDIR/.wh.$UP1BASE
    #v2.11 these also...
    [ -f $OLDDIR/.wh.__dir_opaque ] && rm -f $OLDDIR/.wh.__dir_opaque
   done
   #now check for 'old' files on top layer...
   if [ -f $OLDFILESMNTPT$ONENEW ];then
    #echo -n '.'
    #note, this is inaccurate due to local timezone not yet set...
    #i got this 'stat' off ibiblio, v3.3. i think older version than in main puppy f.s...
    MODIFOLD=`$PUPFILESDIR/bin/stat -c %Y $OLDFILESMNTPT$ONENEW`
    MODIFNEW=`$PUPFILESDIR/bin/stat -c %Y $NEWFILESMNTPT$ONENEW`
    ##or, can do it using find...
    #MODIFOLD=`find $OLDDIR -type f -maxdepth 1 -name $ONEBASE -printf %T@`
    #NEWDIR="`dirname $NEWFILESMNTPT$ONENEW`"
    #MODIFNEW=`find $NEWDIR -type f -maxdepth 1 -name $ONEBASE -printf %T@`
    [ "$PPURGE" = "yes" ] && MODIFNEW=`expr $MODIFOLD + 1` #force overwrite all.
    if [ $MODIFNEW -ge $MODIFOLD ];then
     #v2.12 modify msg...
     #echo "Restoring $ONENEW" >/dev/console
     echo -n " $ONENEW " >/dev/console
     ONEDIR="`dirname $ONENEW`"
     mkdir -p $OLDFILESMNTPT/tmp/versioncleanup$ONEDIR
     cp -af $OLDFILESMNTPT$ONENEW $OLDFILESMNTPT/tmp/versioncleanup$ONEDIR/
     rm -f $OLDFILESMNTPT$ONENEW
    fi
   fi
  done
  echo >/dev/console  #v2.12
  cd /
 fi
 #v2.14 need to cleanup whiteout files if a new .sfs layer has been added...
 if [ "$NEWUNIONRECORD" != "" -o "$PPURGE" = "yes" ];then
  #find all .wh.__dir_opaque files at the OLDFILESMNTPT layer...
  cd $OLDFILESMNTPT
  #v2.15 grep -o option not supported...
  #find ./ -noleaf -type f -name ".wh.*" | grep -o '/.*' |
  find ./ -noleaf -type f -name ".wh.*" | sed -e 's/^\.//g' |
  while read ONEOPAQUE
  do
   ONEDIR="`dirname $ONEOPAQUE`"
   WHBASE="`basename $ONEOPAQUE`"
   if [ ! "$WHBASE" = ".wh.__dir_opaque" ];then #v2.14
    #example, .wh.bin alongside bin directory means it is deleted...
    ONEDEL="`echo -n "$WHBASE" | sed -e 's/^\.wh\.//g'`"
    BASEDIR="`basename $ONEDIR`"
    [ ! "$BASEDIR" = "$ONEDEL" ] && continue
   fi
   #if same dir exists lower layer, then wipe the opaque file...
   #if [ "$PPURGE" = "yes" ];then
    [ -d /pup_ro3${ONEDIR} ] && rm -f $ONEOPAQUE
    [ -d /pup_ro4${ONEDIR} ] && rm -f $ONEOPAQUE
    [ -d /pup_ro5${ONEDIR} ] && rm -f $ONEOPAQUE
   #else
   # for NEWDIR in $NEWSFS
   # do
   #  [ -d ${NEWDIR}${ONEDIR} ] && rm -f $ONEOPAQUE
   # done
   #fi
  done
  cd /
 fi
 #set this back so rc.update will also do version update after pivot_root...
 #[ "$PPURGE" = "yes" ] && echo -n "$OLDPVERSION" > $OLDFILESMNTPT/etc/puppyversion
 if [ $NEWPVERSION -gt $OLDPVERSION ];then
  echo -n "$OLDPVERSION" > $OLDFILESMNTPT/etc/puppyversion #v2.14 so rc.update will run.
  sync
  echo -e "\\033[1;35m"  >/dev/console #34=blue, 33=yellow, 32=green, 31=red, 35=purple, 36=aquablue, 38=black.
  [ "$PCLEAN" = "yes" ] && echo "This is a simulated version upgrade, which performs a file cleanup." >/dev/console
  [ "$PPURGE" = "yes" ] && echo "This is a radical file cleanup for broken systems, could alter some settings." >/dev/console
  echo "You are upgrading Puppy from version $OLDPVERSION to $NEWPVERSION." >/dev/console
  echo "Overwritten old files have been moved to /tmp/versioncleanup/" >/dev/console
  echo "After bootup please examine this directory (before shutdown) for anything" >/dev/console
  echo "that you might like to recover. Pausing 30 secs so you can read this msg..." >/dev/console
  echo -en "\\033[0;39m" >/dev/console
  sleep 30 #so can see above messages.
 fi
fi


#can ignore case-2 i think, as it does not use initrd...
#no, could have PUPMODE=2 and this script executing (for some usbhd installations that use syslinux)...
if [ ! $PUPMODE -eq 2 ];then
#now do the unionfs thing...
 mkdir -p /pup_rw/etc/rc.d
 echo "PUPMODE=$PUPMODE" > /pup_rw/etc/rc.d/PUPSTATE #to be read by rc.shutdown.
 #Dougal pointed out the ' is technically wrong here, but bash sets the
 #mode by the outer ", meaning the $PDEV1 gets substituted...
 echo "PDEV1='$PDEV1'" >> /pup_rw/etc/rc.d/PUPSTATE     # "
 echo "DEV1FS='$FSTYPE'" >> /pup_rw/etc/rc.d/PUPSTATE     # "
 echo "PUPSFS='$PUPSFS'" >> /pup_rw/etc/rc.d/PUPSTATE   # "
 echo "PUPSAVE='$PUPSAVE'" >> /pup_rw/etc/rc.d/PUPSTATE # "
 echo "PMEDIA='$PMEDIA'" >> /pup_rw/etc/rc.d/PUPSTATE   # "
 echo "SATADRIVES='$SATADRIVES'"  >> /pup_rw/etc/rc.d/PUPSTATE
 #v2.12...
 echo '#these directories are unionfs layers in /initrd...' >> /pup_rw/etc/rc.d/PUPSTATE
 echo "SAVE_LAYER='$OLDFILESMNTPT'" >> /pup_rw/etc/rc.d/PUPSTATE
 echo "PUP_LAYER='$NEWFILESMNTPT'" >> /pup_rw/etc/rc.d/PUPSTATE
 if [ $ZDRV ];then
  echo '#this file has kernel and other drivers...' >> /pup_rw/etc/rc.d/PUPSTATE
  echo "ZDRV='$ZDRV'" >> /pup_rw/etc/rc.d/PUPSTATE
 fi
 if [ $SMNTPT ];then
  if [ "`echo -n "$SMNTPT" | grep '/mnt/'`" != "" ];then
   echo "#The partition that has the $PUPSAVE file is mounted here..." >> /pup_rw/etc/rc.d/PUPSTATE
   echo "PUP_HOME='${SMNTPT}'" >> /pup_rw/etc/rc.d/PUPSTATE
   echo '#(in /initrd) ...note, /mnt/home is a link to it.' >> /pup_rw/etc/rc.d/PUPSTATE
  fi
 fi

 #[ $PUPMODE -eq 5 ] && echo -n "$MORE1SFS" > /pup_rw/etc/rc.d/MORE1SFS # "
 #...not used, see rc.shutdown.
 #echo -n "$PUPPYVERSION" > /pup_rw/etc/puppyversion #used to check saved session at bootup
 #...no, need to do this in rc.update.
 mkdir /pup_rw/initrd 2>/dev/null
 sync
 echo -n "Creating unionfs on (/initrd)/pup_new (to become '/')..." >/dev/console
 #v2.16 exit to initial ramdisk shell...
 if [ "$RDSH" = "5" ];then
  echo "Exit before executing: mount -t aufs -o udba=reval,diropq=w,dirs=${UMNT1}${UMNTRO} unionfs /pup_new" >/dev/console
  exec /bin/sh >/dev/console 2>&1
 fi
 #v2.15 changed 'none' to 'unionfs'... 
 #v2.16alpha now aufs, also udba=reval (the default anyway i think)
 #v2.16alpha try diropq=w...
 if [ $aufs ];then #v2.16rc
  mount -t aufs -o udba=reval,diropq=w,dirs=${UMNT1}${UMNTRO} unionfs /pup_new;check_status $?
  #...v2.16alpha leave the second 'unionfs' string there.
 else
  mount -t unionfs -o dirs=${UMNT1}${UMNTRO} unionfs /pup_new;check_status $?
 fi
 
 ########special initramfs stuff########
 #v2.15 cpio archive does switch_root, lose the initial-ramdisk, move all mntd...
 mkdir -p /pup_new/initrd
 mkdir -p /pup_new/initrd/pup_ro1
 mkdir -p /pup_new/initrd/pup_ro2
 mkdir -p /pup_new/initrd/pup_ro3
 mkdir -p /pup_new/initrd/pup_ro4
 mkdir -p /pup_new/initrd/pup_ro5
 mkdir -p /pup_new/initrd/pup_rw
 mkdir -p /pup_new/initrd/mnt
 mkdir -p /pup_new/initrd/mnt/dev_ro1
 mkdir -p /pup_new/initrd/mnt/dev_save
 mkdir -p /pup_new/initrd/mnt/swap
 mkdir -p /pup_new/initrd/mnt/tmpfs
 mkdir -p /pup_new/initrd/mnt/zdrv
 for ONEMNT in `mount | cut -f 3 -d ' ' | grep -v 'pup_new' | grep '^/pup_' | tr '\n' ' '`
 do
  mount -o move $ONEMNT /pup_new/initrd${ONEMNT}
 done
 for ONEMNT in `mount | cut -f 3 -d ' ' | grep '^/mnt/' | tr '\n' ' '`
 do
  mount -o move $ONEMNT /pup_new/initrd${ONEMNT}
 done
 #move the modules to main f.s....
 if [ ! -d /pup_new/lib/modules/$KERNVER/initrd ];then
  cp -a /modules/$KERNVER /pup_new/lib/modules/$KERNVER/initrd
  sync
  #note1: switch_root will delete them in ramdisk
  #note2: /etc/rc.d/rc.modules will gunzip them and run depmod.
 fi
 #/etc/profile prevents X from starting if this file exists...
 [ "$PNOX" = "yes" ] && touch /pup_new/tmp/bootcnt.txt
 cp -a /PUPPYVERSION /pup_new/initrd/
 mkdir -p /pup_new/initrd/tmp
 cp -a /tmp/*.log /pup_new/initrd/tmp/
 #boot scripts in main f.s. may want access to this info...
 echo "$PUPFNDACC" > /pup_new/initrd/tmp/pupfound.log #accumulated results of analyse_pupfound_func
 #swap partition gets messed up after switch_root. quick hack, thanks to Rob Landley...
 mkdir -p /pup_new/initrd/dev
 [ "$SWAPPART" != "" ] && mount -o move /dev /pup_new/initrd/dev
 #v2.16rc can use either unionfs or aufs...
 [ $aufs ] && ln -sf snapmergepuppy-aufs /pup_new/initrd/usr/sbin/snapmergepuppy
 ##########end special initrams stuff########
 
else
 echo "PUPMODE=2" > /pup_rw/etc/rc.d/PUPSTATE #to be read by rc.shutdown.
 echo "SATADRIVES='$SATADRIVES'"  >> /pup_rw/etc/rc.d/PUPSTATE
fi

#want to launch dnotify from init script as it is pristine...
#/sbin/launchpupsafe &

#exit to initial ramdisk shell...
[ "$RDSH" = "yes" ] && exec /bin/sh >/dev/console 2>&1

sync
umount /proc/bus/usb #v2.15
umount /proc

##v2.15 now using cpio archive for initrd...
#v2.15 humongous initrd... make zdrv file visible to modprobe script in main f.s....
[ -f "/zdrv_${PUPPYVERSION}.sfs" ] && [ ! -f "/pup_new/zdrv_${PUPPYVERSION}.sfs" ] && mv /zdrv_${PUPPYVERSION}.sfs /pup_new/zdrv_${PUPPYVERSION}.sfs
#exec switch_root -c /dev/console /pup_new /bin/busybox init 3
exec switch_root /pup_new /sbin/init

#v2.15 old code, no longer used...
#cd /pup_new #v2.15 removed
##echo "pivot_root now changing from initial ramdisk..."
#pivot_root . initrd
##v2.15 humongous initrd... make zdrv file visible to modprobe script...
#[ -f "/initrd/zdrv_${PUPPYVERSION}.sfs" ] && ln -fs /initrd/zdrv_${PUPPYVERSION}.sfs /zdrv_${PUPPYVERSION}.sfs
#exec chroot . sh -c "exec /bin/busybox init"  <dev/console >dev/console 2>&1


###END###
