#!/bin/sh
#(c) Copyright 2007 Barry Kauler, www.puppylinux.com
#2007 Lesser GPL licence v2 (http://www.fsf.org/licensing/licenses/lgpl.html)
#Aug 2007, init script in initramfs, for puppy v2.20, Sept: v3.00, Oct: v3.01
#Nov 2007, v3.91: bugfix for humongous puppy.
#dec 2007, v3.93: update for 2.6.24 kernel, no /dev/hd*. v3.94: bugfix.
#v3.95 28dec07: load scsi_wait_scan.ko to fix sync problem with usb.
#v3.95 1jan08: fix for renaming of pmedia ide/sata -> ata.
#v3.96 26jan08: 2.6.24 kernel, remove scsi_wait_scan.ko and the delays.
#v3.97 31jan2008: restore support for hd* drives.
#v3.97 25feb2008: removed tmpfs on /tmp.
#v3.97 5mar2008: handle SAVEMARK file (see universal installer and rc.shutdown).
#v3.97 6mar2008: fix 'pfix=ram' for multisession cd/dvd.
#v3.97 6mar2008: multisession, copy saved .sfs files to '/' in ram.
#v3.98 3apr2008: partial fix, encrypted pup_save losetup failing.
#v4.00 21apr2008: ntfs-3g upgraded v1.417 to v1.2412.
#v4.00 26apr2008: slightly lowered threshold for copying pup_xxx.sfs to a tmpfs.
#v4.00 27apr2008: k2.6.25: strange sync problem. try restore scsi_wait_scan. NO, DO NOT.
#v4.01 7may2008: new system with all modules builtin to initrd, if ZDRVINIT='yes'
#v4.02 31may2008: export ZDRVINIT in /etc/rc.d/PUPSTATE
#v403 21jun08: reintroduce basic pcmcia support.
#v403 23jun08: fix for humongous initrd.
#v403 23jun08: fix boot from usb cd drive (classmate laptop).
#v404 13Jul08: pfix=noram removed, now need pfix=copy to copy .sfs to ram.
#v404 15jul08: prevent crash in PUPMODE 6,7. add pfix=fsck, otherwise never do fsck.
#v404 16jul08: fix for classmate with internal usb flash, PUPMODE now 13, not 12.
#v405 18jul08: default is now aufs. maybe won't even have unionfs module.
#v406 2aug08: restore support for old /dev/hd* ide devices.
#v406 9aug08: copy pup_xxx.sfs to same place as pup_save if fast media.
#v407 fix for module name change.
#v410 fix to allow 3 extra sfs files (a bug only allowed 2).
#v411 multisession, load saved /dev entries.
#v412 simplified module loading.
#v412 slight changes for new busybox v1.12.1.
#v412 fix usb-storage probe bug.
#v412 DISTRO_SPECS file. pup_xxx.sfs, zdrv_xxx.sfs renamed.
#v412 bugfix, /tmp/versioncleanup got overwritten by tmpfs mounted on /tmp.
#v412 bugfix, pup_ro6 was not created (for 3rd sfs file).
#w001 DISTRO_FILE_PREFIX, pup files renamed again, to woofsave.2fs, woofr001.sfs.
#w003 fix for loading yenta-socket module.
#w003 changed default to copy woofr001.sfs to ram >256MB ram.
#w003 /usr/sbin/snapmergepuppy now saves whiteout files to save-layer, change 'ro' to 'ro+wh'.
#w004 LANG=C
#w007 load nls_utf8.ko
#w012 bugfix. w014 usb flash can now have iso9660 f.s.
#w014 BootFlash utility can create 2 partitions in usb drive, one for boot, other for save.
#w015 allow 6 extra sfs files, up from 3.
#w019 pmedia=ataflash, PUPMODE=13 to constrain writes to drv.
#w460 bugfixes for zdrv, new name zu500629.sfs, handling 6 extra sfs files (7 incl. zdrv).
#w460 bugfix, boot usb, 1st shutdown was not offering to save session sometimes.
#w464 tidyup, make sure /etc/puppyversion is history.
#w468 load nls_cp850, now default for fat f.s. (2.6.29.2 kernel).
#w476 mntfunc() rewritten, support 'pkeys' boot param (work in progress).
#w478 modify sfs exclusion rules.
#w479 fix finding optical drive for kernel with old ide drivers.
#w481 record fast partitions, used by rc.shutdown.
#w482 lowered limit for copy sfs to ram, so multisession will work in 256mb pc.
#v423 k2.6.29.6 dmesg has warning that ehci-hcd should load before uhci-hcd and ohci-hid.
#v423 problem recent kernels: hid-* extra drivers needed as well as usbhid.
#v423 need to reject wrong squashfs version, 3.x or 4.0.
#v424 BootManager no longer has checkbox to only load _nnn.sfs files.
#v424 try again, fix tmpfs overwrites /tmp/versioncleanup
#v424 whiteout processing for aufs2 fixed.
#v426 pkeys=de caused failure to boot from vfat partition.
#v426 record of layers needs to include zdrv.
#v431 piratesmack: fix boot from ext4.
#091031 support quirky, kernel with initramfs built-in, maybe also <main f.s.>.sfs.
#091122 now have /lib/keymaps, /lib/consolefonts, load map if pkeys boot param.
#091222 first support for recognising mmc/sd cards at bootup.
#091225 copy executables from initrd to main f.s.
#100113 TARGETEXES file needed in main f.s., for universal installer.
#100214 one config of 2.6.33 has base floppy and ps/2 mouse support not builtin.
#100222 fix sync problem writing to BOOTCONFIG. technosaurus: consider very big puppies.
#100318 fix any improper shutdowns. see /etc/rc.d/rc.sysinit, rc.shutdown, /sbin/init.
#100323 hwclock path was wrong.
#100401 fix so pupsave can be ext2, ext3 or ext4.
#100406 latest patched aufs may allow sfs mntd one layer to be resident another layer.

#Unionfs layers setup by this script...
#unionfs layers:            RW (top)      RO1             RO2              PUPMODE
#full install, flash drive: tmpfs         PDEV1                            3
#First boot (or pfix=ram):  tmpfs                         pup_xxx.sfs      5
#pup_save is a partition:   PDEV1                         pup_xxx.sfs      6
#ditto, but flash drive:    tmpfs         PDEV1           pup_xxx.sfs      7
#Normal running puppy:      pup_save.3fs                  pup_xxx.sfs      12
#ditto, but flash drive:    tmpfs         pup_save.3fs    pup_xxx.sfs      13
#Multisession cd/dvd:       tmpfs         folders(tmpfs2) pup_xxx.sfs      77 (13+64)

#/bin/hotplug2stdout_notimeout > /tmp/pup_event_uevents_initrd &
export LANG=C #w004
. /DISTRO_SPECS #v412 has DISTRO_VERSION, DISTRO_FILE_PREFIX
[ ! $DISTRO_MINOR_VERSION ] && DISTRO_MINOR_VERSION=00 #091031

PATH="/bin:/sbin"
KERNELVER="`uname -r`"

KERNELSUBVER=`echo -n "$KERNELVER" | cut -f 3 -d '.' | cut -f 1 -d '-'` #v423
SFSSTR='squashfs, version 3' #v423
[ $KERNELSUBVER -gt 28 ] && SFSSTR='squashfs, version 4' #v423

#w020 compose name of 'zdrv', to fit 8+3 filename...
PREFIX1CHAR="`echo -n "$DISTRO_FILE_PREFIX" | cut -c 1`"
KERNEL3CHARS="`echo -n "$KERNELVER" | tr -d '.' | tr -d '\-' | tr -d '[a-z]' | rev | cut -c 1,2,3 | rev`"
ZDRVSFS="z${PREFIX1CHAR}${DISTRO_VERSION}${KERNEL3CHARS}.sfs"

#091031 compose name of quirky kernel...
zDISTRO_FILE_PREFIX="`echo -n "$DISTRO_FILE_PREFIX" | cut -c 1-4`"
zDISTRO_BINARY_COMPAT="`echo -n "$DISTRO_BINARY_COMPAT" | cut -c 1`"
QUIRKYKERNEL="${zDISTRO_FILE_PREFIX}${DISTRO_VERSION}.${zDISTRO_BINARY_COMPAT}${DISTRO_MINOR_VERSION}"

[ $layerfs ] && LAYERFS=$layerfs
[ ! $LAYERFS ] && LAYERFS=aufs #aufs or unionfs
[ "`modinfo aufs 2>/dev/null`" = "" ] && LAYERFS=aufs #precaution.

[ $loglevel ] && LOGLEVEL=$loglevel #v2.22

#100318 perform a f.s. check...
fsckme_func() { #passed params: partition filesystem [pupsavefile]
 case $2 in
  ext2|ext3|ext4)
   e2fsck -y -f /dev/$1 >/tmp/chkret &
   echo -e "\\033[1;35m" >/dev/console #35=purple
   if [ "${1}" = "loop1" ];then
    echo -n " 'save file' filesystem check, please wait..." >/dev/console
   else
    echo -n " '${1}' filesystem check, please wait..." >/dev/console
   fi
   while [ "`pidof e2fsck`" != "" ];do
    sleep 1
    echo -n "." >/dev/console
   done
   echo -en "\\033[0;39m" >/dev/console
  ;;
 esac
 if [ $3 ];then
  #rc.shutdown has created /fsckme.err with this 3rd parameter.
  #this is a pupsave file, which has a ext2/3/4 f.s (based on .2fs, .3fs, .4fs ext)
  #this flag will be set for any prior improper shutdown. if have lots of installations
  #of puppy on the pc, the flag may not even be for this install of puppy, however, this is
  #the simplest implementation...
  PFSCK="yes"
 fi
}

mntfunc() {
 MNT_T="$1"    #ex: vfat
 MNT_DEV="$2"  #ex: /dev/sda1
 MNT_DIR="$3"  #ex: /mnt/sda1
 MNT_O=""
 [ $4 ] && MNT_O="${4}" #ex: noatime
 case $MNT_T in
  ntfs)
   ntfs-3g $MNT_DEV $MNT_DIR -o umask=0,no_def_opts,noatime,rw 2>/dev/null #default is rw
   ntfsRETVAL=$?
   [ $ntfsRETVAL -eq 0 ] && return 0
   if [ $ntfsRETVAL -eq 14 ];then
    #ntfs-3g $MNTPRMS -o umask=0,no_def_opts,noatime,rw,remove_hiberfile 2>/dev/null
    echo -e "\\033[1;31m" >/dev/console #31=red
    echo -n "ERROR: Windows NTFS hibernated partition, cannot mount" > /dev/console
    echo -e "\\033[0;39m" >/dev/console
    return 14
   else
    ntfs-3g $MNT_DEV $MNT_DIR -o umask=0,no_def_opts,noatime,rw,force 2>/dev/null
   fi
  ;;
  vfat)
   mount -t $MNT_T -o $VFAT_OUT_PARAM $MNT_DEV $MNT_DIR
  ;;
  *)
   if [ "$MNT_O" = "" ];then
    mount -t $MNT_T $MNT_DEV $MNT_DIR
   else
    mount -t $MNT_T -o $MNT_O $MNT_DEV $MNT_DIR
   fi
  ;;
 esac
 return $?
}

umntfunc() {
 #warning umntfunc call must have mntpt param, not device name.
 LASTPARAM="`echo -n "$*" | tr '\t' ' ' | tr -s ' ' | tr ' ' '\n' | grep '^/mnt/'`"
 if [ "`mount | grep "$LASTPARAM" | grep -E 'ntfs|fuse'`" = "" ];then
  umount $@
 else
  fusermount -u $LASTPARAM
 fi
 return $?
}

check_status()
{
  /bin/echo -en "\\033[72G" >/dev/console #move to column 72.
  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
    #exit to initial ramdisk shell...
    [ "$RDSH" != "" ] && exec /bin/sh >/dev/console 2>&1
    echo "Pausing for 60 seconds..." >/dev/console
    sleep 60
  fi
}

#PUPPYVERSION=`cat /PUPPYVERSION`
#kernel with /proc/ide...
#pmedia= usbflash|usbhd|usbcd|ideflash|idehd|idecd|idezip|satahd|satacd|scsihd|scsicd|cd
#kernel without /proc/ide (libata PATA)...
#pmedia= usbflash|usbhd|usbcd|ataflash|atahd|atacd|atazip|scsihd|scsicd|cd
[ $pmedia ] && PMEDIA=$pmedia #boot parameter, broad category of boot media. ex: cd.
[ $pdev1 ] && PDEV1=$pdev1    #boot parameter, partition have booted off. ex: hda3
[ $psubdir ] && PSUBDIR=$psubdir #boot parameter, directory for puppy files. ex: puppy220
[ $pkeys ] && PKEYS=$pkeys #boot parameter, keyboard layout w476
WAITUSB=yes
[ $nousbwait ] && WAITUSB=no #boot parameter, keyboard layout w476
[ $ramboot ] && RAMBOOT=yes
[ $forcepupmode ] && FORCEPUPMODE=$forcepupmode



#now supporting a boot menu...
RDSH=""
if [ "$pfix" ];then
 for ONEFIX in `echo -n "$pfix" | tr ',' ' '`
 do
  case $ONEFIX in
   ram)     PRAMONLY="yes";;      #run in ram only (do not load ${DISTRO_FILE_PREFIX}save).
   rdsh)    RDSH="yes";;          #exit to shell in initial ramdisk.
   rdsh0)   RDSH="0";;            #drop out early, before loading drivers.
   rdsh6)   RDSH="6";;            #w091027 drop out just before mount layerfs.
   nox)     PNOX="yes";;          #do not start X.
   clean)   PCLEAN="yes";;        #force version upgrade and cleanup.
   purge)   PPURGE="yes";;        #radical cleanup for broken system.
   copy)    PCOPY="yes";;         #copy .sfs files into ram.
   fsck)    PFSCK="yes";;         #do a fsck of ${DISTRO_FILE_PREFIX}save file.
   [0-9]*)  PIGNORELAST=$ONEFIX;; #blacklist last $ONEFIX folders (multisession).
  esac
 done
fi


mount -t proc none /proc
mount -t sysfs none /sys
mount -t rootfs -o remount,rw rootfs /
ln -s /proc/mounts /etc/mtab #resize2fs,e2fsck need this.

#v3.95 for backwards naming compatibility...
if [ ! -e /proc/ide ];then #v3.97
 [ "$PMEDIA" = "ideflash" ] && PMEDIA="ataflash"
 [ "$PMEDIA" = "idezip" ] && PMEDIA="atazip"
 [ "$PMEDIA" = "idehd" ] && PMEDIA="atahd"
 [ "$PMEDIA" = "idecd" ] && PMEDIA="atacd"
 [ "$PMEDIA" = "satahd" ] && PMEDIA="atahd"
 [ "$PMEDIA" = "satacd" ] && PMEDIA="atacd"
fi

clear #got this out of embutils, compiled in t2 (as not currently in busybox)
[ ! "$LOGLEVEL" ] && exec 1>/tmp/bootinit.log 2>&1 #remove o/p from console. v2.22 loglevel added.

export TZ='XXX-23' #100318 imaginary place right around the world east of Greenwich.
#...i think that this will give the most delayed time, so any file operations
#will not result in a future date after the correct time is set in the main puppy f.s.
#ref: http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html
/bin/hwclock --hctosys --localtime #set system time (based on hw clock set to local time).

#does this initrd have all the zdrv components inside it?...
ZDRVINIT='no'
[ `wc -l /lib/modules/$KERNELVER/modules.dep  | tr -s ' ' | cut -f 2 -d ' '` -gt 200 ] && ZDRVINIT='yes'

#091122 load keyboard layout if PKEYS boot param...
STATUS=0
VFAT_OUT_PARAM='shortname=mixed,quiet'
FONTMAP=""
CODEPAGE=""
KMAP=""
if [ "$PKEYS" ];then
 if [ ! -f /lib/keymaps/${PKEYS}.gz ];then
  PKEYS="`ls -1 /lib/keymaps/${PKEYS}*.gz | head -n 1 | rev | cut -f 1 -d '/' | cut -f 2 -d '.' | rev`"
 fi
 echo "Loading '${PKEYS}' keyboard layout..." >/dev/console
 if [ -f /lib/keymaps/${PKEYS}.gz ];then
  KMAP="$PKEYS"
  zcat /lib/keymaps/${PKEYS}.gz | loadkmap ; STATUS=$(($STATUS + $?))
  case $PKEYS in 
   de*|be*|br*|dk*|es*|fi*|fr*|it*|no*|se*|pt*)
    modprobe nls_cp850
    FONTMAP="lat1-12.psfu"
    CODEPAGE="850"
    VFAT_OUT_PARAM="$OUT_PARAM"',codepage=850'
   ;;
   cz*|hu*|pl*|ro*|sk*|croat*|slovene*)
    modprobe nls_cp852
    modprobe nls_iso8859-2
    FONTMAP="lat2-12.psfu"
    CODEPAGE="852"
    VFAT_OUT_PARAM="$OUT_PARAM"',codepage=852,iocharset=iso8859-2'
   ;;
  esac
  [ "$FONTMAP" ] && zcat /lib/consolefonts/${FONTMAP}.gz | loadfont ; STATUS=$(($STATUS + $?))
 else
  STATUS=1
 fi
 check_status $STATUS
fi

[ "$RDSH" = "0" ] && exec /bin/sh >/dev/console 2>&1 #w091222

###################LOAD MODULES TO ACCESS DRIVES#####################
echo -n "Loading drivers needed to access disk drives" > /dev/console #STEP ONE

#100214 one config of 2.6.33 has base floppy and ps/2 mouse support not builtin...
[ "`modinfo floppy 2>/dev/null`" != "" ] && modprobe floppy
[ "`modinfo psmouse 2>/dev/null`" != "" ] && modprobe psmouse

#w462 if present, load it. enables recognition of drives attached to parallel port.
[ "`modinfo ppa 2>/dev/null`" != "" ] && modprobe ppa #also loads parport.ko

ELSPCI="`elspci -l`" #jesses great little utility.
#v403 pcmcia drive support. i think this may need extra delay though...
if [ "`echo "$ELSPCI" | grep '060700'`" != "" ];then
 modprobe yenta_socket
 #...may have to add on a couple of seconds, need to test with a pcmcia drive.
 #v412 yeah, my pccard-usb adaptor needs delay before elspci recognises 0C0310 (ohci-hcd) interface...
 sleep 2
fi
#v423 k2.6.29.6 dmesg has warning that ehci-hcd should load before uhci-hcd and ohci-hid
# this is contrary to my understanding all these years, but oh well, let's do it...
[ "`echo "$ELSPCI" | grep '0C0320'`" != "" ] && modprobe ehci-hcd

MODALIASES="`cat /sys/bus/pci/devices/*/modalias`" #important, save to variable before loop.
for ONEMODALIAS in $MODALIASES
do
  modprobe -v $ONEMODALIAS #-v means verbose.
  [ $? -eq 0 ] && echo -n "." > /dev/console
done

#091222 some mmc/sd interfaces need this...
#(above code loop may have loaded sdhci/sdhci_pci or tifm_core/tifm_7xx1)
[ "`lsmod | grep '^sdhci'`" != "" ] && modprobe mmc_core && modprobe mmc_block
[ "`lsmod | grep '^tifm'`" != "" ] && modprobe mmc_core && modprobe mmc_block && modprobe tifm_sd

modprobe squashfs
if [ -e /proc/ide ];then #v3.97
 modprobe cdrom
 modprobe ide-cd
fi
modprobe sr_mod > /dev/null 2>&1 #v3.93 now built-in to 2.6.25.x kernel.

#ATADRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"
ATADRIVES="`ls -1 /sys/block | grep '^sd' | tr '\n' ' '`"

echo -n "$ATADRIVES" > /ATADRIVES #w479 for testing purposes if crash to console.

#if [ "`lsmod | grep -E '^uhci|^ohci|^ehci'`" != "" ];then
  modprobe usb-storage & #run as separate process
  #WAITUSB="yes"
  mount -t usbfs none /proc/bus/usb
  
  #v423 problem recent kernels: kernel configured to load hid-* extra drivers when
  #usbhid loads, but it doesn't work. Most unfortunate. Note, older kernels have the
  #hid-* (drivers for specific hardware, like Logitech wireless keyboard) builtin to
  #the usbhid driver. Now that they are separated out, it is a headache. Try this...
  /bin/hotplug2stdout_notimeout >/tmp/uevents.log &
  PIDHOT=$!
  modprobe usbhid #for a usb keyboard.
#fi

#v3.95 driver now builtin to libata pata kernel...
if [ -e /proc/ide ];then #v3.97
 #ide zip or ide ls-120 drive?...
 [ ! "`dmesg | grep "ATAPI FLOPPY"`" = "" ] && modprobe ide-floppy
fi

#filesystems...
modprobe nls_cp437     #needed by windows filesystems.
modprobe nls_iso8859-1 #needed by linux filesystems.
#modprobe nls_utf8 #w007
#modprobe nls_cp850 #w468 now default for fat f.s. (2.6.29.2 kernel)
modprobe $LAYERFS #unionfs or aufs.
modprobe fuse #for ntfs-3g driver.

if [ "$WAITUSB" = "yes" ];then #wait for device to register.
 #v3.94 Classmate laptop, needs more delay here... no, further down...
 sleep 1 #2 v403 bumped it up to 3. v412 try 1sec again.
 USBSTORAGES=0 ; CNTUSB=0
 while [ $USBSTORAGES -eq 0 ];do
  echo -n "." > /dev/console
  sleep 1
  CNTUSB=`expr $CNTUSB + 1`
  [ $CNTUSB -gt 25 ] && break
  #v412 bug, ubuntu kernel, got duplicate 'device found at 2', need 'sort -u'...
  USBSTORAGES=`/bin/dmesg | grep "usb-storage: device found at" | sort -u | wc -l | sed -e 's/ //g'`
  #if booting from usb, USBSTORAGES must be non-zero...
  [ "`echo "$PMEDIA" | grep 'usb'`" != "" ] && [ $USBSTORAGES -eq 0 ] && continue
  [ $USBSTORAGES -eq 0 ] && break
  AVAILABLEUSBSTORAGES=`/bin/dmesg | grep "usb-storage: device scan complete" | wc -l | sed -e 's/ //g'`
  [ $USBSTORAGES -ne $AVAILABLEUSBSTORAGES ] && USBSTORAGES=0
 done
 [ $USBSTORAGES -ne 0 ] && sleep 1 #v412 was needed for classmate. was 2, try 1sec.
 
 #v423 load hid-* driver...
 for ONEHID in `grep -o 'MODALIAS=hid:[^ ]*' /tmp/uevents.log | cut -f 2 -d '=' | tr '\n' ' '`
 do
  modprobe $ONEHID
 done
 kill $PIDHOT
 
fi

check_status 0 #END STEP ONE
##############END MODULE LOADING TO ACCESS DRIVES####################

#######################FINDING PUPPY FILES###########################
echo -n "Searching for Puppy files in computer disk drives..." > /dev/console #STEP TWO
#locate all partitions (and superfloppy drives)...
PCPARTSALL="`probepart_init -k`"
PCPARTS0="`echo "$PCPARTSALL" | grep '^/dev/' | cut -f 1-2 -d '|'  | grep -E 'iso9660|ext2|ext3|ext4|reiserfs|msdos|vfat|minix|ntfs' | sed -e 's/\/dev\///g'`" #v431
PCPARTS="`echo "$PCPARTS0" | tr "\n" " "`" #note, will have a space char on end.

#want separate lists of all internal (fast) partitions, and slow (usb) partitions...
FASTPARTS=""
PCPARTS0_NOCDS="`echo "$PCPARTS0" | grep -v '^sr'`" #w014 removed 'iso9660' test as now usb flash can have it.
#w479 ...not good enough. extra check for old kernel with ide drivers...
if [ -e /proc/ide ];then #w479
 OLDCDDRV="`echo "$PCPARTS0" | grep 'iso9660' | grep '^hd' | cut -f 1 -d '|' | head -n 1`"
 [ "$OLDCDDRV" != "" ] && PCPARTS0_NOCDS="`echo "$PCPARTS0_NOCDS" | grep -v "$OLDCDDRV"`"
fi
SLOWPARTS0="$PCPARTS0_NOCDS" #not right, but will eliminate wrong ones.
#v3.97 last section superfluous for libata PATA kernel...
for ONEFAST in $ATADRIVES `cat /proc/partitions | grep "hd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`
do
 APATTERN="^${ONEFAST}"
 FASTPARTS="${FASTPARTS}`echo "$PCPARTS0_NOCDS" | grep "$APATTERN" | tr '\n' ' '`"
 SLOWPARTS0="`echo "$SLOWPARTS0" | grep -v "$APATTERN"`"
done
FASTPARTS0="`echo "$FASTPARTS" | tr -s ' ' | tr ' ' '\n'`"
SLOWPARTS="`echo "$SLOWPARTS0" | tr '\n' ' '`"
CDPARTS0="`echo "$PCPARTS0" | grep -E '^sr|^hd' | grep 'iso9660'`" #w014 w479
CDPARTS="`echo "$CDPARTS0" | tr '\n' ' '`"

#need to narrow the search...
case $PMEDIA in
 *cd) #booting from usb, sata, or ide cd drive.
  LESSPARTS0="$PCPARTS0" #need to search everywhere.
  [ "$PRAMONLY" = "yes" ] && LESSPARTS0="$CDPARTS0" #v2.22
  ;;
 usb*) #external boot media. exs: usbflash, usbhd
  LESSPARTS0="$SLOWPARTS0"
  ;;
 *hd|*flash|*zip) #internal boot media. ex: idehd, satahd, ideflash, idezip, scsihd
  LESSPARTS0="$FASTPARTS0"
  ;;
 *)
  LESSPARTS0="$PCPARTS0" #need to search everywhere.
  ;;
esac
#in case PDEV1 boot param., override...
if [ "$PDEV1" ];then
 APATTERN="${PDEV1}|"
 LESSPARTS0="`echo "$PCPARTS0" | grep "$APATTERN"`"
fi
LESSPARTS="`echo "$LESSPARTS0" | tr '\n' ' '`"

#find puppy files in the pc...
touch /tmp/PUPPYFILES
for ONETRY in $LESSPARTS
do
 FND_FULLINSTALL=""
 ONEDEV="`echo -n "$ONETRY" | cut -f 1 -d '|'`"
 ONEFS="`echo -n "$ONETRY" | cut -f 2 -d '|'`"
 #v403 nasty bug: usb optical drive showing as /sys/block/sr0, but won't mount, needs more delay...
 mntfunc $ONEFS /dev/$ONEDEV /mnt/data #-t $ONEFS /dev/$ONEDEV /mnt/data
 if [ $? -ne 0 ];then
  sleep 5 #2 wasn't enough.
  mntfunc $ONEFS /dev/$ONEDEV /mnt/data #-t $ONEFS /dev/$ONEDEV /mnt/data
  [ $? -ne 0 ] && continue
 fi
 [ -f /mnt/data/etc/puppyversion ] && FND_FULLINSTALL="/etc/puppyversion" #pre-w464 installations.
 [ -f /mnt/data/etc/DISTRO_SPECS ] && FND_FULLINSTALL="/etc/DISTRO_SPECS"
 FND_QUIRKYKERNEL="`find /mnt/data -maxdepth 2 -xdev -type f -name ${QUIRKYKERNEL} | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 FND_INITRDGZ="`find /mnt/data -maxdepth 2 -xdev -type f -name initrd.gz | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 #v3.01 '*' means zero or more extra characters. this is for custom naming...
 FND_PUPXXXSFS="`find /mnt/data -maxdepth 2 -xdev -type f -name ${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.sfs | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 FND_ZDRVSFS="`find /mnt/data -maxdepth 2 -xdev -type f -name ${ZDRVSFS} | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 FND_PUPSAVE2FS="`find /mnt/data -maxdepth 2 -xdev -type f -name ${DISTRO_FILE_PREFIX}save*.[234]fs | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 FND_SWAPFILEPUP="`find /mnt/data -maxdepth 2 -xdev -type f -name pupswap.swp | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 #v2.22 improved folder name search, avoid false hits...
 FND_MULTIFOLDER="`find /mnt/data -maxdepth 1 -xdev -type d -name 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9] | grep -v ' ' | sed -e 's%^/mnt/data%%g' | tr '\n' ' '`"
 [ "$FND_MULTIFOLDER" != "" ] && echo "$ONEDEV $ONEFS $FND_MULTIFOLDER" >> /tmp/MULTIFOLDERS
 #all written on one line...
 echo -n "$ONEDEV $ONEFS " >> /tmp/PUPPYFILES
 echo "FND_QUIRKYKERNEL $FND_INITRDGZ $FND_PUPXXXSFS $FND_ZDRVSFS $FND_PUPSAVE2FS $FND_MULTIFOLDER $FND_FULLINSTALL $FND_SWAPFILEPUP" >> /tmp/PUPPYFILES
 [ -f /mnt/data/SAVEMARK ] && PSAVEMARK="`cat /mnt/data/SAVEMARK`" #v3.97 partition# that has or will-have ${DISTRO_FILE_PREFIX}save.
 #100318 fix any improper shutdowns... fsckme.err format: sda7,ext3,[/pupsave.2fs] (see rc.shutdown)
 FSCKME=""
 [ -f /mnt/data/fsckme.err ] && FSCKME="`cat /mnt/data/fsckme.err | tr ',' ' ' | tr '\n' ' '`"
 rm -f /mnt/data/fsckme.err
 umntfunc /mnt/data
 [ "$FSCKME" ] && fsckme_func $FSCKME
done

#in case PSUBDIR boot param (path of puppy files), filter...
if [ "$PSUBDIR" ];then
 SPATTERN="/${PSUBDIR}/"
 PUPPYFILES="`grep "$SPATTERN" /tmp/PUPPYFILES | head -n 1 | tr -s ' '`" #v3.00...
 if [ "$PUPPYFILES" ];then
  PDEV1="`echo -n "$PUPPYFILES" | cut -f 1 -d ' '`" #v3.01
  DEV1FS="`echo -n "$PUPPYFILES" | cut -f 2 -d ' '`" #v3.01
  xpupfiles="`echo -n "$PUPPYFILES" | cut -f 3-99 -d ' ' | tr ' ' '\n' | grep "$SPATTERN" | tr '\n' ' '`" #v3.01
  PUPPYFILES="$PDEV1 $DEV1FS $xpupfiles"
 fi
else
 PUPPYFILES="`cat /tmp/PUPPYFILES | tr -s ' '`"
fi
echo "$PUPPYFILES" > /tmp/PUPPYFILES

#a humongous initrd has ${DISTRO_FILE_PREFIX}rxxx.sfs inside it...
if [ -f /${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.sfs ];then
 #and maybe also ${ZDRVSFS}...
 if [ -f /${ZDRVSFS} ];then
  echo "rootfs rootfs /${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.sfs /${ZDRVSFS}" >> /tmp/PUPPYFILES
 else
  echo "rootfs rootfs /${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.sfs" >> /tmp/PUPPYFILES
 fi
 PUPPYFILES="`cat /tmp/PUPPYFILES`" #v3.91
fi

if [ ! "$PDEV1" ];then #091031 quirky
 QUIRKYPART="`grep "$QUIRKYKERNEL" /tmp/PUPPYFILES | head -n 1`"
 if [ "$QUIRKYPART" != "" ];then
  PDEV1="`echo -n "$QUIRKYPART" | cut -f 1 -d ' '`"
  DEV1FS="`echo -n "$QUIRKYPART" | cut -f 2 -d ' '`"
 fi
fi

if [ ! "$PDEV1" ];then
 #note, if 'psubdir' defined, PDEV1 already found above.
 #if only one line in /tmp/PUPPYFILES has initrd.gz then that must be the boot partition...
 #w460 need extra test to avoid other initrd.gz's...
 SRCH1="`grep '/initrd\\.gz' /tmp/PUPPYFILES`"
 if [ "`echo "$SRCH1" | wc -l`" = "1" ];then
  PDEV1="`echo -n "$SRCH1" | cut -f 1 -d ' '`"
 else
  uPATTERN='/'"${DISTRO_FILE_PREFIX}\\-${DISTRO_VERSION}\\.sfs"
  SRCH2="`echo "$SRCH1" | grep "$uPATTERN"`"
  if [ "`echo "$SRCH2" | wc -l`" = "1" ];then
   PDEV1="`echo -n "$SRCH2" | cut -f 1 -d ' '`"
  fi
 fi
 #v2.20b or, if boot from cd, look for the iso9660 f.s...
 ISITACD="`echo -n "$PMEDIA" |  grep 'cd'`"
 [ "$ISITACD" != "" ] && [ "`grep '/initrd\\.gz' /tmp/PUPPYFILES | grep ' iso9660 ' | wc -l`" = "1" ] && PDEV1="`grep '/initrd\\.gz' /tmp/PUPPYFILES | grep ' iso9660 ' | cut -f 1 -d ' '`"
fi

if [ "$PDEV1" -a ! "$PSAVEMARK" ];then #w014
 #new BootFlash utility can create 128MB boot partition, 2nd partition for pupsave...
 devnameonly="`echo -n "$PDEV1" | sed -e 's/[0-9]*$//'`"
 pdPATTERN='/dev/'"$PDEV1"'|'
 pdSIZEK=`echo "$PCPARTSALL" | grep "$pdPATTERN" | cut -f 3 -d '|'`
 if [ $pdSIZEK -lt 139264 ];then #136MB
  p1PATTERN='/dev/'"$devnameonly"'1|'
  p2PATTERN='/dev/'"$devnameonly"'2|'
  devnumonly="`echo -n "$PDEV1" | sed -e 's/sd[a-z]//'`"
  [ "$devnumonly" = "1" ] && [ "`echo "$PCPARTSALL" | grep "$p2PATTERN"`" != "" ] && PSAVEMARK="2" #USB-HDD or ISO9660.
  [ "$devnumonly" = "4" ] && [ "`echo "$PCPARTSALL" | grep "$p1PATTERN"`" != "" ] && PSAVEMARK="1" #USB-ZIP or ComboFormat.
 fi
fi
if [ "$PDEV1" -a "$PSAVEMARK" ];then #v3.97
 devnameonly="`echo -n "$PDEV1" | sed -e 's/[0-9]*$//'`"
 PUPSAVEDEV="${devnameonly}${PSAVEMARK}" #partition that has or will-have ${DISTRO_FILE_PREFIX}save.2fs.
fi

#find ${DISTRO_FILE_PREFIX}-xxx.sfs and ${DISTRO_FILE_PREFIX}save.2fs files...
touch /tmp/PUPXXXSFSS
touch /tmp/PUPSAVE2FSS
NUMPARTS=`wc -l /tmp/PUPPYFILES | tr -s ' ' | cut -f 2 -d ' '`
case $NUMPARTS in
 0) #nothing found.
  echo -en "\\033[1;31m" >/dev/console #31=red
  echo -n "No Puppy files found. Dropping out to initial-ramdisk console..." >/dev/console
  /bin/echo -e "\\033[0;39m" >/dev/console
  exec /bin/sh >/dev/console 2>&1
  ;;
 *) #files in one or more partitions.
  echo "$PUPPYFILES" |
  while read ONELINE
  do
   #ONELINE has part., f.s., then all puppy files found in that partition, space-delimited.
   #each line written to file has format: hda7,ext3,path/filename...
   ONEDEV="`echo -n "$ONELINE" | cut -f 1 -d ' '`" #ex: hda7
   ONEFS="`echo -n "$ONELINE" | cut -f 2 -d ' '`"  #ex: ext3
   LINEFILES="`echo -n "$ONELINE" | cut -f 3-99 -d ' '`" #ex: /pup220/${DISTRO_FILE_PREFIX}save.2fs /pup220/${DISTRO_FILE_PREFIX}r220.sfs
   APATTERN="/${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.*\\.sfs"
   for ONEPUPXXXSFS in `echo "$LINEFILES" | tr ' ' '\n' | grep "$APATTERN" | tr '\n' ' '`
   do
    echo "$ONEDEV,$ONEFS,$ONEPUPXXXSFS"  >> /tmp/PUPXXXSFSS
   done
   BPATTERN="/${DISTRO_FILE_PREFIX}save.*\\.[234]fs"
   for ONEPUPSAVE2FS in `echo "$LINEFILES" | tr ' ' '\n' | grep "$BPATTERN" | tr '\n' ' '`
   do
    [ "$PUPSAVEDEV" ] && [ "$ONEDEV" != "$PUPSAVEDEV" ] && continue #v3.97
    echo "$ONEDEV,$ONEFS,$ONEPUPSAVE2FS"  >> /tmp/PUPSAVE2FSS
   done
   ZPATTERN="/${ZDRVSFS}"
   for ONEZDRVXXXSFS in `echo "$LINEFILES" | tr ' ' '\n' | grep "$ZPATTERN" | tr '\n' ' '`
   do
    echo "$ONEDEV,$ONEFS,$ONEZDRVXXXSFS"  >> /tmp/ZDRVXXXSFSS #v2.22
   done
  done
  ;;
esac

PUPMODE=0
#choose which ${DISTRO_FILE_PREFIX}save.2fs to use...
if [ -f /tmp/MULTIFOLDERS ];then #multisession cd/dvd.
 if [ "$PRAMONLY" = "yes" ];then #v3.97 fix 'pfix=ram' for multisession dvd.
  PUPSAVE=""
 else
  PUPMODE=72 #77 v3.01 64+8, will become 77.
  PUPSAVE="`cat /tmp/MULTIFOLDERS | cut -f 1-3 -d ' ' | tr ' ' ','`" #only record 1st folder.
 fi
else
 NUMPUPSAVES=`wc -l /tmp/PUPSAVE2FSS | tr -s ' ' | cut -f 2 -d ' '`
 [ "$PRAMONLY" = "yes" ] && NUMPUPSAVES=0 #pfix=ram is a boot param.
 case $NUMPUPSAVES in
  0)
   PUPSAVE=""
   ;;
  1)
   PUPMODE=8 #`expr $PUPMODE + 8`  #PUPMODE=12
   PUPSAVE="`cat /tmp/PUPSAVE2FSS`" #format: hda7,ext3,/pup220/${DISTRO_FILE_PREFIX}save.2fs
   ;;
  *)
   PUPSAVE=""
   CNTSAVE=1
   echo -e "\\033[1;36m" >/dev/console #36=aquablue
   echo "Type a number to choose which personal file to use:" > /dev/console
   echo "0  none" > /dev/console
   for ONECHOICE in `cat /tmp/PUPSAVE2FSS | tr '\n' ' '`
   do
    ONEFILE="`echo -n "$ONECHOICE" | cut -f 3 -d ','`"
    ONEPART="`echo -n "$ONECHOICE" | cut -f 1 -d ','`"
    echo -e "${CNTSAVE}  ${ONEPART}\\033[10G${ONEFILE}" > /dev/console #10 means move to that column.
    CNTSAVE=`expr $CNTSAVE + 1`
   done
   echo -en "\\033[0;39m" >/dev/console
   read NUMSAVE
   #clear
   if [ $NUMSAVE -ne 0 ];then
    PUPMODE=8 #`expr $PUPMODE + 8`  #PUPMODE=12
    PUPSAVE="`cat /tmp/PUPSAVE2FSS | tr '\n' ' ' | cut -f $NUMSAVE -d ' '`"
   fi
   ;;
 esac
fi
#note, PUPSAVE has format: partition,f.s.-of-part.,path/name ex: hda3,ext2,/pup220/${DISTRO_FILE_PREFIX}save.2fs

#choose which ${DISTRO_FILE_PREFIX}-xxx.sfs to use...
PUPSFS=""
#if humongous initrd, use internal ${DISTRO_FILE_PREFIX}-xxx.sfs...
PUPSFS="`cat /tmp/PUPXXXSFSS | grep 'rootfs rootfs'`"
#if already chose a ${DISTRO_FILE_PREFIX}save prefer a ${DISTRO_FILE_PREFIX}-xxx.sfs in same place...
if [ "$PUPSFS" = "" -a "$PUPSAVE" != "" ];then
 PPATTERN='^'"`echo -n "$PUPSAVE" | cut -f 1 -d ','`"','
 PUPSFS="`grep "$PPATTERN" /tmp/PUPXXXSFSS | head -n 1`" #v3.00
fi

if [ "$PUPSFS" = "" ];then
 if [ ! -e /proc/ide ];then #w479
  PUPSFS="`grep -v '^sr' /tmp/PUPXXXSFSS | head -n 1`" #w014 exclude optical, take top.
 else
  #w479 extra check for old kernel with ide drivers, exclude all optical drvs...
  PUPSFS="`grep -v '^sr' /tmp/PUPXXXSFSS`"
  OLDCDDRV="`echo "$PCPARTS0" | grep 'iso9660' | grep '^hd' | cut -f 1 -d '|' | head -n 1`"
  [ "$OLDCDDRV" != "" ] && PUPSFS="`echo "$PUPSFS" | grep -v "$OLDCDDRV" | head -n 1`"
 fi
fi

if [ "$PUPSFS" != "" -a "$PDEV1" != "" ];then #v3.01
 #if booting from cd, make sure chosen has same name as on cd...
 CDPATTERN="^${PDEV1},iso9660"
 CDSFSNAME="`grep "$CDPATTERN" /tmp/PUPXXXSFSS | head -n 1 | cut -f 3 -d ','`"
 if [ "$CDSFSNAME" ];then
  CDSFSBASE="`basename $CDSFSNAME`"
  HDSFSNAME="`echo -n "$PUPSFS" | cut -f 3 -d ','`"
  HDSFSBASE="`basename $HDSFSNAME`"
  [ "$CDSFSBASE" != "$HDSFSBASE" ] && PUPSFS="`grep "$CDPATTERN" /tmp/PUPXXXSFSS | head -n 1`" #use file on cd.
 fi
fi

[ "$PUPSFS" = "" ] && PUPSFS="`cat /tmp/PUPXXXSFSS | head -n 1`"
if [ "$PUPSFS" = "" ];then
 echo -en "\\033[1;31m" >/dev/console #31=red
 echo -n "${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}.sfs not found. Dropping out to initial-ramdisk console..." >/dev/console
 /bin/echo -e "\\033[0;39m" >/dev/console
 exec /bin/sh >/dev/console 2>&1
else
 PUPMODE=`expr $PUPMODE + 4` #${DISTRO_FILE_PREFIX}-xxx.sfs exists.
fi

#choose which ${ZDRVSFS} to use... v2.22
if [ -f /tmp/ZDRVXXXSFSS ];then
 if [ "$PUPSAVE" != "" ];then
  #use zdrv which should be in same place as the '${DISTRO_FILE_PREFIX}save' ${DISTRO_FILE_PREFIX}-xxx.2fs...
  ZPATTERN="^`echo -n "$PUPSAVE" | cut -f 1 -d ','`,"
  ZDRV="`grep "$ZPATTERN" /tmp/ZDRVXXXSFSS | head -n 1`"
 fi
 if [ "$ZDRV" = "" ];then
  #fall back to getting it from same place as ${DISTRO_FILE_PREFIX}-xxx.sfs file...
  ZPATTERN="^`echo -n "$PUPSFS" | cut -f 1 -d ','`,"
  ZDRV="`grep "$ZPATTERN" /tmp/ZDRVXXXSFSS | head -n 1`"
 fi
fi

#refine the PUPMODE...
#if a ${DISTRO_FILE_PREFIX}save was not found, perhaps boot partition has a full install of puppy...
if [ "$PUPSAVE" = "" -a "$PDEV1" != "" ];then
 APATTERN="^${PDEV1} "
 [ "`grep "$APATTERN" /tmp/PUPPYFILES | grep '/etc/puppyversion'`" != "" ] && DEV1PUP="yes" #pre-w464 installations.
 [ "`grep "$APATTERN" /tmp/PUPPYFILES | grep '/etc/DISTRO_SPECS'`" != "" ] && DEV1PUP="yes"
 [ "$DEV1PUP" = "yes" ] && PUPMODE=`expr $PUPMODE + 2`
fi
#do we want a tmpfs top unionfs layer?...
#only if ${DISTRO_FILE_PREFIX}save (or PDEV1 for DEV1PUP=yes, or first boot) on a flash drive, usb or internal...
case $PUPMODE in
 4) #so far have only got a ${DISTRO_FILE_PREFIX}-xxx.sfs. this is first boot or pfix=ram.
  PUPMODE=5 #`expr $PUPMODE + 1` #yes, want tmpfs top layer (PUPMODE=5).
  ;;
 12) #4=${DISTRO_FILE_PREFIX}-xxx.sfs found, 8=${DISTRO_FILE_PREFIX}save.2fs found.  total=12
  DRVSAVE="`echo -n "$PUPSAVE" | cut -b 1-3`"
  REMOVABLEDRVSAVE="`cat /sys/block/$DRVSAVE/removable`"
  [ "$REMOVABLEDRVSAVE" = "1" ] && PUPMODE=13 #`expr $PUPMODE + 1`
  [ "$PMEDIA" = "usbflash" ] && PUPMODE=13 #v404 fix classmate, with internal usb flash.
  [ "$PMEDIA" = "ataflash" -o "$PMEDIA" = "ideflash" ] && PUPMODE=13 #w019 constrain writes to internal flash drv.
  [ `cat /sys/block/${DRVSAVE}/queue/rotational` = 0 ] && PUPMODE=13    
  cat /sys/block/${DRVSAVE}/device/model | egrep "SSD|PHISON|SILICONMOTION SM|FPM32GRES|FTM64GL25H"  
  [ $? = 0 ] && PUPMODE=13    
  echo 0 > /sys/block/${DRVSAVE}/queue/rotational    
  ;;
 6) #4=${DISTRO_FILE_PREFIX}-xxx.sfs found, 2=full install of puppy in boot partition. total=6
  DRVSAVE="`echo -n "$PDEV1" | cut -b 1-3`"
  REMOVABLEDRVSAVE="`cat /sys/block/$DRVSAVE/removable`"
  [ "$REMOVABLEDRVSAVE" = "1" ] && PUPMODE=7 #`expr $PUPMODE + 1`
  #v3.96 Classmate laptop has internal usb flash, so really want the tmpfs layer...
  # puppyinstaller created 'pmedia=usbflash' for the extlinux full hd install...
  [ "$PMEDIA" = "usbflash" ] && PUPMODE=7
  [ "$PMEDIA" = "ataflash" -o "$PMEDIA" = "ideflash" ] && PUPMODE=7 #w019 constrain writes to internal flash drv.
  [ `cat /sys/block/${DRVSAVE}/queue/rotational` = 0 ] && PUPMODE=7    
  cat /sys/block/${DRVSAVE}/device/model | egrep "SSD|PHISON|SILICONMOTION SM|FPM32GRES|FTM64GL25H"  
  [ $? = 0 ] && PUPMODE=7    
  echo 0 > /sys/block/${DRVSAVE}/queue/rotational    
  ;;
 76) #v3.01 64+8+4 multisession cd.
  PUPMODE=77 #`expr $PUPMODE + 1` #yes, want tmpfs top layer.
  ;;
esac
[ ! -z "$FORCEPUPMODE" ] && PUPMODE=$FORCEPUPMODE
[ "$RAMBOOT" = "yes" ] && PUPMODE=12


if [ $PDEV1 ];then
 APATTERN="^${PDEV1}|"
 DEV1FS="`echo "$PCPARTS0" | grep "$APATTERN" | cut -f 2 -d '|'`"
 #v2.20b if booted with PMEDIA=cd, refine it...
 if [ "$PMEDIA" = "cd" ];then
  case $PDEV1 in
   hd*) PMEDIA="idecd" ;; #v3.97
   scd*|sr*)
    PMEDIA="usbcd"
    if [ "`echo -n "$ATADRIVES" | grep "$PDEV1"`" != "" ];then
     if [ -e /proc/ide ];then #v3.97
      PMEDIA="satacd"
     else
      PMEDIA="atacd"
     fi
    fi
    ;;
  esac 
 fi
fi

check_status 0
########################END FINDING PUPPY FILES############################

##########################LOADING PUPPY FILES###########################
RAMSIZE=`free | grep 'Mem:' | tr -s ' ' | cut -f 3 -d ' '` #total physical ram (less shared video).
CRYPTO=""

#decide the mount-points...
#unionfs layers:            RW (top)      RO1             RO2              PUPMODE
#full install, flash drive: tmpfs         PDEV1                            3
#First boot (or pfix=ram):  tmpfs                         pup_xxx.sfs      5
#pup_save is a partition:   PDEV1                         pup_xxx.sfs      6
#ditto, but flash drive:    tmpfs         PDEV1           pup_xxx.sfs      7
#Normal running puppy:      pup_save.3fs                  pup_xxx.sfs      12
#ditto, but flash drive:    tmpfs         pup_save.3fs    pup_xxx.sfs      13
#Multisession cd/dvd:       tmpfs         folders(tmpfs2) pup_xxx.sfs      77
CREATETMPFS="";CREATEPDEV1="";CREATEPUPXXXSFS="";CREATEPUPSAVE2FS="";CREATEFOLDERS=""
case $PUPMODE in #w003 changed some save-layer to 'ro+wh' so that whiteouts files are recognised...
 3)  CREATETMPFS="/pup_rw";CREATEPDEV1="/pup_ro1"
     OLDFILESMNTPT="/pup_ro1";NEWFILESMNTPT="/pup_ro1";UMNTMAIN="/pup_rw=rw:/pup_ro1=ro+wh";;
 5)  CREATETMPFS="/pup_rw";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro2=ro";;
 6)  CREATEPDEV1="/pup_rw";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="/pup_rw";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro2=ro";;
 7)  CREATETMPFS="/pup_rw";CREATEPDEV1="/pup_ro1";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="/pup_ro1";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro1=ro+wh:/pup_ro2=ro";;
 12) CREATEPUPSAVE2FS="/pup_rw";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="/pup_rw";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro2=ro";;
 13) CREATETMPFS="/pup_rw";CREATEPUPSAVE2FS="/pup_ro1";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="/pup_ro1";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro1=ro+wh:/pup_ro2=ro";;
 77) CREATETMPFS="/pup_rw";CREATEFOLDERS="/pup_ro1";CREATEPUPXXXSFS="/pup_ro2"
     OLDFILESMNTPT="/pup_ro1";NEWFILESMNTPT="/pup_ro2";UMNTMAIN="/pup_rw=rw:/pup_ro1=ro+wh:/pup_ro2=ro";;
 *)  RDSH="yes";; #precaution.
esac

if [ "$CREATEPDEV1" != "" ];then
 [ "`echo "$DEV1FS" | grep 'ext[234]'`" != "" ] && echo "/dev/$PDEV1 $CREATEPDEV1 $DEV1FS defaults  1 1" >> /etc/fstab #v2.21
 mount -t $DEV1FS /dev/$PDEV1 $CREATEPDEV1
 #save is not a ${DISTRO_FILE_PREFIX}save file, but a partition on a unionfs layer...
 if [ "$CREATEPDEV1" = "/pup_rw" -o "$CREATEPDEV1" = "/pup_ro1" ];then #v2.20b
  SMNTPT="$CREATEPDEV1"
  PUPSAVE="$PDEV1,$DEV1FS,/" #deliberately left last param as only /.
 fi
fi

if [ "$CREATEPUPSAVE2FS" != "" ];then
 PUPSAVEDEV="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"
 PUPSAVEFS="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
 PUPSAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
 #normal ${DISTRO_FILE_PREFIX}save.2fs file. just mount it from where it is...
 echo -n "Loading personal file $PUPSAVEFILE ($PUPSAVEDEV)..." > /dev/console 
 [ "`echo "$PUPSAVEFS" | grep 'ext[234]'`" != "" ] && echo "/dev/$PUPSAVEDEV /mnt/dev_save $PUPSAVEFS defaults  1 1" >> /etc/fstab #v2.21
 if [ "$RAMBOOT" = "yes" ] ; then
        if [ "$PUPSAVEDEV" = '' ] ; then
                echo -e -n " \\033[1;31mError, Save file is required for ramboot option  \\033[0;39m" 
                exit
        fi
        mntfunc $PUPSAVEFS /dev/$PUPSAVEDEV /mnt/tmpfs3 noatime
        cd /mnt/tmpfs3/${PSUBDIR}
        SIZE=0
	SIZE=`ls *fs | while read line ; do SIZEK=$(du -k $line| cut -f 1); SIZE=$(expr $SIZE + $SIZEK); echo $SIZE ; done |tail -n 1`
        SIZE=`expr $SIZE + 1000`
        if [ $SIZE -gt $RAMSIZE ] ; then
                echo -e -n " \\033[1;31mError, Files too big to fit in RAM  \\033[0;39m" > /dev/consol
                exit
        fi
        mount -t tmpfs -o size=${SIZE}k tmpfs /mnt/dev_save
        mkdir /mnt/dev_save/$PSUBDIR
        echo -e  " \\033[1;35mCopying files to RAM  \\033[0;39m" > /dev/console #purple.
        echo -e  " \\033[1;35m${SIZE}KB RAM will be used\\033[0;39m" > /dev/console
        ls *fs |while read line ; do
                echo -e -n " \\033[1;35m${line} \\033[0;39m" > /dev/console #purple.
                cp -af ${line} /mnt/dev_save/$PSUBDIR > /dev/console 2>&1
        done
        cd
        umntfunc /mnt/tmpfs3
 else
      mntfunc $PUPSAVEFS /dev/$PUPSAVEDEV /mnt/dev_save noatime #-t $PUPSAVEFS -o noatime /dev/$PUPS
 fi
 if [ $? -eq 0 ];then
  SMNTPT="/mnt/dev_save"
  #is the ${DISTRO_FILE_PREFIX}save encrypted?...
  if [ ! "`echo "$PUPSAVEFILE" | grep '_crypt'`" = "" ];then
   case $PUPSAVEFILE in 
    *cryptx*) #see /etc/rc.d/rc.shutdown.
     CRYPTO='-E 1' #v2.16final '-e xor' --bug, loads xor.ko which is something else.
     modprobe cryptoloop
     ;;
    *)
     CRYPTO='-e aes'
     modprobe cryptoloop
     modprobe aes_generic 2>/dev/null #v407 aes name change.
     modprobe aes 2>/dev/null #for older kernel <2.6.25
     modprobe crypto_blkcipher 2>/dev/null #v407 blkcipher name change.
     modprobe blkcipher 2>/dev/null #old kernel.
     modprobe cbc
     ;;
   esac
  fi
  if [ "$CRYPTO" != "" ] ; then
   echo "" >/dev/console
   echo "Mounting encrypted $PUPSAVEFILE..." > /dev/console
   while true; do
    #note, cryptoloop does not work with jounalled fs, hence have to use ext2 only.

    #v3.01 will take this out as a func later (similar code below)...
    #about to mount ${DISTRO_FILE_PREFIX}save.2fs, but before that check if need to resize it...
    if [ -f /mnt/dev_save/pupsaveresize.txt ];then #created by /usr/sbin/resizepfile.sh
     KILOBIG=`cat /mnt/dev_save/pupsaveresize.txt`
     rm -f /mnt/dev_save/pupsaveresize.txt
     echo > /dev/console
     echo -n "Increasing $PUPSAVEFILE by $KILOBIG Kbytes, please wait..." >/dev/console
     dd if=/dev/zero bs=1024 count=$KILOBIG >> /mnt/dev_save$PUPSAVEFILE
     sync
     if [ "$CRYPTO" = "-e aes" ];then #v3.98
      echo "NOTICE: As you type your password nothing will be displayed on the" >/dev/console
      echo "screen for absolute security. Just type it in then press ENTER key..." >/dev/console
      echo -e "\\033[1;36m" >/dev/console #aqua-blue
      echo -n "Password: " >/dev/console
      echo -en "\\033[0;39m" >/dev/console
      read -s MYPASS #< /dev/console v403
      echo "$MYPASS" | losetup -p 0 -e aes /dev/loop1 /mnt/dev_save$PUPSAVEFILE
     else
      echo -e "\\033[1;36m" >/dev/console #aqua-blue
      echo -n "Password: " >/dev/console
      echo -en "\\033[0;39m" >/dev/console
      #losetup does not accept -p param for xor encryption... may not work...
      losetup $CRYPTO /dev/loop1 /mnt/dev_save$PUPSAVEFILE
     fi
     e2fsck -y -f /dev/loop1
     resize2fs -pf /dev/loop1 #no size, will fill all of file.
     sync
     #check_status 0 #note, e2fsck gives an error even though it works. v2.21 maybe okay now.
     echo -n "...continuing with loading $PUPSAVEFILE..." > /dev/console
    else
     echo -e "\\033[1;36m" >/dev/console #aqua-blue
     echo -n "Password: " >/dev/console
     echo -en "\\033[0;39m" >/dev/console
     if [ "$CRYPTO" = "-e aes" ];then #v3.98
      read -s MYPASS #< /dev/console v403
      echo "$MYPASS" | losetup -p 0 -e aes /dev/loop1 /mnt/dev_save$PUPSAVEFILE
     else
      #losetup does not accept -p param for xor encryption... may not work...
      losetup $CRYPTO /dev/loop1 /mnt/dev_save$PUPSAVEFILE
     fi
    fi

    echo "/dev/loop1 $CREATEPUPSAVE2FS ext2 defaults  1 1" >> /etc/fstab #v2.21
    #[ "$PFSCK" = "yes" ] && fsckme_func loop1 ext2 #100318 however, commented out as there was an old not that f.s. check on an encrypted pupsave is broken.
    mount -t ext2 -o noatime,rw /dev/loop1 $CREATEPUPSAVE2FS #only ext2 allowed.
    MNTSTAT=$?
    if [ "$MNTSTAT" = "0" ] ; then
     echo -n "...successfully mounted" >/dev/console
     break
    else 
     echo -en "\\033[1;31m" >/dev/console #31=red
     echo "Can't mount file, press ENTER key to try again, or" >/dev/console
     echo "any other char then ENTER for f.s. check then try again, or " > /dev/console
     echo -n "for developers type 'quit' to drop out to console: " > /dev/console
     echo -en "\\033[0;39m" >/dev/console
     read crypttryagain
     echo > /dev/console
     [ "$crypttryagain" = "quit" ] &&  exec /bin/sh >/dev/console 2>&1 #v3.98
     [ "$crypttryagain" != "" ] && e2fsck -y -f /dev/loop1 >/dev/console
     losetup -d /dev/loop1
    fi
   done
  else #pupsave not encrypted.
   #about to mount ${DISTRO_FILE_PREFIX}save.2fs, but before that check if need to resize it...
   if [ -f /mnt/dev_save/pupsaveresize.txt ];then #created by /usr/sbin/resizepfile.sh
    KILOBIG=`cat /mnt/dev_save/pupsaveresize.txt`
    rm -f /mnt/dev_save/pupsaveresize.txt
    echo > /dev/console
    echo -n "Increasing $PUPSAVEFILE by $KILOBIG Kbytes, please wait..." >/dev/console
    dd if=/dev/zero bs=1024 count=$KILOBIG >> /mnt/dev_save$PUPSAVEFILE
    sync
    e2fsck -y -f /mnt/dev_save$PUPSAVEFILE
    resize2fs -pf /mnt/dev_save$PUPSAVEFILE #no size, will fill all of file.
    sync
    check_status 0 #note, e2fsck gives an error even though it works. v2.21 maybe okay now.
    echo -n "...continuing with loading $PUPSAVEFILE..." > /dev/console
   fi
   losetup /dev/loop1 /mnt/dev_save${PUPSAVEFILE}
   SFFS='ext'`echo -n "$PUPSAVEFILE" | rev | cut -c 3`
   echo "/dev/loop1 $CREATEPUPSAVE2FS $SFFS defaults  1 1" >> /etc/fstab
   [ "$PFSCK" = "yes" ] && fsckme_func loop1 $SFFS #100318
   mount -t $SFFS -o noatime /dev/loop1 $CREATEPUPSAVE2FS
   if [ $? -ne 0 ];then
    e2fsck -y -f /dev/loop1 > /dev/console #-y answer yes to all repair questions.
    mount -t $SFFS -o noatime /dev/loop1 $CREATEPUPSAVE2FS
   fi
  fi
 fi
 check_status $?
fi

#there are technical problems with loading a swap partition/file before the union
#is created, so not doing it until rc.sysinit runs. however, if a tmpfs needs to be
#created here, set it's size in anticipation of a swap being loaded...
EXTRAALLOCK=0 ; PSWAPFILE=""
SWAPPART="`echo "$PCPARTSALL" | grep '|swap|' | head -n 1`"
[ "$SWAPPART" != "" ] && SWAPPARTSIZE=`echo -n "$SWAPPART" | cut -f 3 -d '|'`
[ $SWAPPARTSIZE ] && EXTRAALLOCK=`expr $SWAPPARTSIZE \/ 2`
if [ "$PDEV1" != "" -a $EXTRAALLOCK -eq 0 ];then
 APATTERN="^${PDEV1} "
 SWAPFILE="`grep "$APATTERN" /tmp/PUPPYFILES | tr ' ' '\n' | grep 'pupswap.swp' | head -n 1`"
 [ "$SWAPFILE" != "" ] && [ -f ${SMNTPT}${SWAPFILE} ] && SWAPFILESIZEBYTES=`stat -c %s ${SMNTPT}${SWAPFILE}`
 if [ $SWAPFILESIZEBYTES ];then
  SWAPFILESIZE=`expr $SWAPFILESIZEBYTES \/ 2048` #use half.
  EXTRAALLOCK=`expr $EXTRAALLOCK + $SWAPFILESIZE`
  PSWAPFILE="$PDEV1,$DEV1FS,$SWAPFILE"
 fi
fi

FREEK=0
if [ "$CREATETMPFS" != "" ];then
 FREEK=`expr $RAMSIZE \/ 2` #half of physical.
 [ $PUPMODE -eq 77 ] && FREEK=`expr $FREEK - 50000` #need some slack.
 ALLOCK=`expr $FREEK + $EXTRAALLOCK`
 mount -t tmpfs -o size=${ALLOCK}k tmpfs $CREATETMPFS
fi

#RW (top) layer now has a tmpfs, PDEV1 or ${DISTRO_FILE_PREFIX}save mounted on it. calc free space...
[ $FREEK -eq 0 ] && FREEK=`df | grep ' /pup_rw' | tr -s ' ' | cut -f 4 -d ' '`
[ ! $FREEK ] && FREEK=0

if [ "$CREATEFOLDERS" != "" ];then
 PUPSAVEDEV="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"
 PUPSAVEFS="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
 PUPSAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
 mount -o noatime -t $PUPSAVEFS /dev/$PUPSAVEDEV /mnt/dev_ro1 #mnt the cd.
 #create a tmpfs to load the folders...
 ALLOCK=`expr $RAMSIZE \/ 2 - 50000` #allocate half of physical ram. + leave 50M slack.
 mount -t tmpfs -o size=${ALLOCK}k tmpfs $CREATEFOLDERS #/pup_ro1
 #load the folders from the cd...
  ####START LOAD FOLDERS####
  CDMNTPT="/mnt/dev_ro1" #where the multisession cd is mounted.
  DESTDIR="$CREATEFOLDERS" #dest dir has a tmpfs mntd on it, into which to copy folders.
  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...
    [ -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
    [ -d $CDMNTPT/$ONEFOLDER/dev ] && cp -a -u $CDMNTPT/$ONEFOLDER/dev $DESTDIR/   > /dev/null 2>&1 #v411
    cp -a -u $CDMNTPT/$ONEFOLDER/*.sfs $DESTDIR/   > /dev/null 2>&1 #v3.97
    #delete deleted files (.wh.filename)...
    WHITEOUTS="`find $DESTDIR -xdev -type f -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 #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 LOAD FOLDERS####    
 umount /mnt/dev_ro1 #unmount the cd.
fi

OLDDISTRO_VERSION=$DISTRO_VERSION
[ -f $OLDFILESMNTPT/etc/puppyversion ] && OLDDISTRO_VERSION=`cat $OLDFILESMNTPT/etc/puppyversion` #old pre-w464 installation.
[ -f $OLDFILESMNTPT/etc/DISTRO_SPECS ] && OLDDISTRO_VERSION=`grep '^DISTRO_VERSION' $OLDFILESMNTPT/etc/DISTRO_SPECS | cut -f 2 -d '=' | cut -f 1 -d ' '` #w012 w478

#move modules to main f.s...
#(do this before loading ${DISTRO_FILE_PREFIX}rxxx.sfs, to free up ram space)...
REASON=''
if [ "$ZDRVINIT" = "yes" ];then
 #the entire kitchen sink of modules is in the initrd.
 ZDRV='' #/sbin/modprobe needs this.
 [ $DISTRO_VERSION -gt $OLDDISTRO_VERSION ] && REASON='upgrade'
 [ $PUPMODE -eq 5 ] && REASON='firstboot'
 #what if deleted modules due to lack space in ${DISTRO_FILE_PREFIX}save, but now more free space?... v4.01...
 [ ! -d /pup_rw/lib/modules/all-firmware ] && [ ! -d /pup_ro1/lib/modules/all-firmware ] && [ $FREEK -gt 24000 ] && REASON='restore'
 if [ "$REASON" != "" ];then
  [ -d /pup_rw/lib/modules ] && rm -rf /pup_rw/lib/modules
  [ -d /pup_ro1/lib/modules ] && rm -rf /pup_ro1/lib/modules
  mkdir -p /pup_rw/lib
  mv /lib/modules /pup_rw/lib/
  mkdir -p /pup_rw/initrd
  cp -af /DISTRO_SPECS /pup_rw/initrd/
  cp -af /init /pup_rw/initrd/
  sync
 fi
else
 #the initrd does have some modules, move them to the main layered f.s...
 #v4.02 moved this up. had it down after the the unionfs setup (just want it same place as the above code).
 [ ! -d /pup_rw/lib/modules/$KERNELVER/initrd ] && [ ! -d /pup_ro1/lib/modules/$KERNELVER/initrd ] && REASON="new"
 if [ "$REASON" != "" ];then
  mkdir -p /pup_rw/lib/modules/$KERNELVER #PUPMODE=5, this dir not exist.
  mv /lib/modules/$KERNELVER /pup_rw/lib/modules/$KERNELVER/initrd
  rm -f /pup_rw/lib/modules/$KERNELVER/initrd/modules.*
  sync
  #note: /etc/rc.d/rc.sysinit will detect them and run depmod.
 fi
 #v3.91 a humongous initrd may have zdrv file...
 [ -f /${ZDRVSFS} ] && [ ! -f /pup_rw/${ZDRVSFS} ] && [ ! -f /pup_ro1/${ZDRVSFS} ] && cp -a /${ZDRVSFS} /pup_rw/
fi

#v405 decide whether to copy sfs's to ram...
COPY2RAM=""
COPYMSG='copying to ram' #purple
#v4.00 lowered rom 230000 to 220000... v403 added PUPSFSDEVMNTPT test... v404 explicit PCOPY needed...
[ $PUPMODE -eq 5 ] && PCOPY="yes" #well, override on first boot.
[ $PUPMODE -eq 77 ] && PCOPY="yes" #v406 multisession dvd.

#100406 this came about because aufs did not work if an sfs mounted via loop device as one layer
#was actually resident on another layer. however latest patched aufs may allow this...
if [ $KERNELSUBVER -lt 33 ];then
 #v404 absolutely must copy to ram, otherwise layerfs conflict...
 [ $PUPMODE -eq 6 -o $PUPMODE -eq 7 ] && COPY2RAM="yes"
 [ "$COPY2RAM" = "yes" ] && COPYMSG='forced copying to ram' #purple
fi

#w482 lower this again, so multisession will work in 256MB system...
#[ $RAMSIZE -gt 260000 -a "$PCOPY" = "yes" ] && COPY2RAM="yes" #256MB system. note, only checking physical ram. w003 incr. from 220000.
[ $RAMSIZE -gt 220000 -a "$PCOPY" = "yes" ] && COPY2RAM="yes" #note, only checking physical ram.

if [ "$CREATEPUPXXXSFS" != "" ];then
 #load ${DISTRO_FILE_PREFIX}-xxx.sfs...
 PUPSFSDEV="`echo -n "$PUPSFS" | cut -f 1 -d ','`"
 PUPSFSFS="`echo -n "$PUPSFS" | cut -f 2 -d ','`"
 PUPSFSFILE="`echo -n "$PUPSFS" | cut -f 3 -d ','`"
 basepupsfs="`basename $PUPSFSFILE`"
 
 #v406 copy ${DISTRO_FILE_PREFIX}rxxx.sfs to same place as ${DISTRO_FILE_PREFIX}save if fast-partition (in case not already)...
 COPYPUPSFS2DIR=""
 if [ "$CREATEPUPSAVE2FS" != "" ];then
  if [ -f /mnt/dev_save$PUPSAVEFILE ];then
   dirsavefile="`dirname $PUPSAVEFILE`"
   fPATTERN='^'"$PUPSAVEDEV"'|'
   if [ "`echo -n "$FASTPARTS0" | grep "$fPATTERN"`" != "" ];then
    #the ${DISTRO_FILE_PREFIX}save is on a fast media.
    if [ ! -f /mnt/dev_save${dirsavefile}/${basepupsfs} ];then
     COPYPUPSFS2DIR="/mnt/dev_save${dirsavefile}"
    fi
   fi
  fi
 fi
 
 echo -n "Loading the '${basepupsfs}' main file..." > /dev/console
 if [ "$PUPSFSDEV" = "rootfs" ];then #humongous initrd.
  PUPSFSDEVMNTPT="" #actually it's '/'.
 else
  PPATTERN="/dev/$PUPSFSDEV "
  PUPSFSDEVMNTPT="`mount | grep "$PPATTERN" | cut -f 3 -d ' '`"
  [ "$RAMBOOT" = "yes" ] && PUPSFSDEVMNTPT=/mnt/dev_save
  if [ "$PUPSFSDEVMNTPT" = "" ];then
   mntfunc $PUPSFSFS /dev/$PUPSFSDEV /mnt/dev_ro2 #-t $PUPSFSFS /dev/$PUPSFSDEV /mnt/dev_ro2
   PUPSFSDEVMNTPT="/mnt/dev_ro2"
   UMOUNTME="/mnt/dev_ro2" #mark for unmounting.
  fi
  
  if [ "$COPYPUPSFS2DIR" ];then #v406 copy ${DISTRO_FILE_PREFIX}-xxx.sfs to same place as ${DISTRO_FILE_PREFIX}save...
   echo -e -n " \\033[1;35mcopying to ${PUPSAVEDEV}\\033[0;39m" > /dev/console #purple.
   ZFILE="`echo "$ZDRV" | cut -f 3 -d ','`"   
   cp -f ${PUPSFSDEVMNTPT}${ZFILE} ${COPYPUPSFS2DIR}/
   cp -f ${PUPSFSDEVMNTPT}${PUPSFSFILE} ${COPYPUPSFS2DIR}/
   if [ $? -eq 0 ];then
    sync
    PUPSFSDEVMNTPT="$COPYPUPSFS2DIR"
    PUPSFS="${PUPSAVEDEV},${PUPSAVEFS},${PUPSFSFILE}"
    PUPSFSDEV="$PUPSAVEDEV"
    PUPSFSFS="$PUPSAVEFS"
   fi
  fi
  
 fi
 #if there's heaps of ram, copy ${DISTRO_FILE_PREFIX}-xxx.sfs to a tmpfs...
 [ "$PUPSFSDEVMNTPT" = "" ] && COPY2RAM="yes"
 #v405 fast media plus more than 256MB ram then definitely worth copying to ram...
 SIZESFSK=`du -k ${PUPSFSDEVMNTPT}${PUPSFSFILE} | cut -f 1`
 SIZESFSK=$(($SIZESFSK + 1000)) #some slack.
 MINRAM2CPY=$(($SIZESFSK * 2)) #100222 technosaurus: in case of very big puppies.
 [ "`echo -n "$FASTPARTS0" | grep "$PUPSFSDEV"`" != "" ] && [ $RAMSIZE -gt 280000 ] && [ $RAMSIZE -gt $MINRAM2CPY ] && COPY2RAM="yes"
 [ "$RAMBOOT" = "yes" ] && COPY2RAM=""
 if [ "$COPY2RAM" = "yes" ];then
  #SIZESFSK=`du -k ${PUPSFSDEVMNTPT}${PUPSFSFILE} | cut -f 1`
  #SIZESFSK=`expr $SIZESFSK + 1000` #some slack.
  mount -t tmpfs -o size=${SIZESFSK}k tmpfs /mnt/tmpfs
  if [ "${PUPSFSDEVMNTPT}" = "" ];then #v403 humongous initrd.
    mv -f ${PUPSFSDEVMNTPT}${PUPSFSFILE} /mnt/tmpfs/
  else
   echo -e -n " \\033[1;35m${COPYMSG}\\033[0;39m" > /dev/console #purple.
   cp -af ${PUPSFSDEVMNTPT}${PUPSFSFILE} /mnt/tmpfs/
  fi
  sync
  SFSBASENAME="`basename $PUPSFSFILE`"
  losetup /dev/loop0 /mnt/tmpfs/${SFSBASENAME}
#  [ "$UMOUNTME" != "" ] && umntfunc $UMOUNTME
 else
  losetup /dev/loop0 ${PUPSFSDEVMNTPT}${PUPSFSFILE}
 fi
 mount -r -t squashfs -o noatime /dev/loop0 $CREATEPUPXXXSFS #usually /pup_ro2.
fi

ZLAYER='' #v4.02
ZFACTOR='' #v426
#note, traditionally, loop2 kept free for scripts to use.
if [ "$ZDRVINIT" != "yes" ];then
 #v4.02 if ZDRV located, and mounted, put it into the unionfs...
 if [ "$ZDRV" != "" ];then
  ZDEV="`echo "$ZDRV" | cut -f 1 -d ','`"
  ZFS="`echo "$ZDRV" | cut -f 2 -d ','`"
  ZFILE="`echo "$ZDRV" | cut -f 3 -d ','`"
  MNT_ZFILE=""
  [ -f /mnt/dev_save${ZFILE} ] && MNT_ZFILE="dev_save"
  [ "$MNT_ZFILE" = "" ] && [ -f /mnt/dev_ro2${ZFILE} ] && MNT_ZFILE="dev_ro2"
  ZBASENAME="`basename $ZFILE`" #v426 moved up.
  if [ "$MNT_ZFILE" != "" ];then
   #w020 do not ever copy it to ram... w460 restore choice...
   if [ "$COPY2RAM" = "yes" ];then #256MB system. note, only checking physical ram.
    SIZEZK=`du -k /mnt/${MNT_ZFILE}${ZFILE} | cut -f 1`
    SIZEZK=`expr $SIZEZK + 1000` #some slack.
    mount -t tmpfs -o size=${SIZEZK}k tmpfs /mnt/tmpfs2
    cp -af /mnt/${MNT_ZFILE}${ZFILE} /mnt/tmpfs2/
    sync
    losetup /dev/loop3 /mnt/tmpfs2/${ZBASENAME}
   else
    losetup /dev/loop3 /mnt/${MNT_ZFILE}${ZFILE}
   fi
   mount -r -t squashfs -o noatime /dev/loop3 /pup_z
   if [ $? -eq 0 ];then
    ZLAYER=':/pup_z=ro'
    ZFACTOR="$ZBASENAME" #v426
   fi
  fi
 fi
fi

check_status $?
########################END LOADING PUPPY FILES########################


#/etc/PUPSTATE passes useful variables to the running puppy...
mkdir -p /pup_rw/etc/rc.d
echo "PUPMODE=$PUPMODE" > /pup_rw/etc/rc.d/PUPSTATE
echo "PDEV1='$PDEV1'" >> /pup_rw/etc/rc.d/PUPSTATE
echo "DEV1FS='$DEV1FS'" >> /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
if [ -e /proc/ide ];then
 echo "SATADRIVES='$ATADRIVES'"  >> /pup_rw/etc/rc.d/PUPSTATE
else
 echo '#v3.97: kernel with libata pata has both sata and pata drives in ATADRIVES...' >> /pup_rw/etc/rc.d/PUPSTATE
 echo "ATADRIVES='$ATADRIVES'"  >> /pup_rw/etc/rc.d/PUPSTATE
fi
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 [ $SMNTPT ];then
 echo "#The partition that has the ${DISTRO_FILE_PREFIX}save 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
echo '#this file has extra kernel drivers and firmware...' >> /pup_rw/etc/rc.d/PUPSTATE
echo "ZDRV='$ZDRV'" >> /pup_rw/etc/rc.d/PUPSTATE #v2.22
echo '#complete set of modules in the initrd (moved to main f.s.)...' >> /pup_rw/etc/rc.d/PUPSTATE
echo "ZDRVINIT='$ZDRVINIT'" >> /pup_rw/etc/rc.d/PUPSTATE #v4.02
echo "PSWAPFILE='$PSWAPFILE'" >> /pup_rw/etc/rc.d/PUPSTATE
echo "PSAVEMARK='$PSAVEMARK'" >> /pup_rw/etc/rc.d/PUPSTATE

#w481 record fast partititons, used by rc.shutdown...
if [ "$FASTPARTS" = " " -o "$FASTPARTS" = "" ];then
 echo "FASTPARTS=''" >> /pup_rw/etc/rc.d/PUPSTATE
else
 echo "FASTPARTS='$FASTPARTS'" >> /pup_rw/etc/rc.d/PUPSTATE
fi

#older ${DISTRO_FILE_PREFIX}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 variable.

######################SETUP UNIONFS LAYERED FILESYSTEM########################
echo -n "Setting up the layered filesystem..." > /dev/console #STEP FIVE
#are there any other sfs files to load at bottom layers?...
NEWUNIONRECORD=""
if [ "$PUPSAVE" != "" ];then
 if [ "$SMNTPT" != "" -o $PUPMODE -eq 77 ];then #v3.97
  SFSSDIR="$SMNTPT"
  [ $PUPMODE -eq 77 ] && SFSSDIR="$DESTDIR" #v3.97
  #find all the extra sfs files...
  touch /tmp/LOGONEBASES
  #v424 modified to only load selection made in BootManager...
  if [ "$EXTRASFSLIST" != "" ];then #in /etc/rc.d/BOOTCONFIG
   ls -1 $SFSSDIR/*.sfs |
   while read ONEEXTRA
   do
    ONEBASE="`basename $ONEEXTRA`"
    exPATTERN="^z|^pup_" #w478
    [ "`echo "$ONEBASE" | grep -E "$exPATTERN"`" != "" ] && continue
    [ "`echo "$EXTRASFSLIST" | grep "$ONEBASE"`" != "" ] && echo "${ONEEXTRA}" >> /tmp/EXTRASFSS
   done
  fi
  UMNTRO="" ; EXTRASFSLIST=""
  if [ -f /tmp/EXTRASFSS ];then
   CNTLOOP=4
   for ONEEXTRA in `cat /tmp/EXTRASFSS | tr '\n' ' '`
   do
    #v423 need to reject wrong squashfs version... v424 no, don't bother...
    #[ "`disktype $ONEEXTRA | grep "$SFSSTR"`" = "" ] && continue
    ONEBASE="`basename $ONEEXTRA`"
    EXTRASFSLIST="${EXTRASFSLIST}${ONEBASE} " #construct list of actually used.
    losetup /dev/loop${CNTLOOP} $ONEEXTRA
    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 10 ] && break
    #...only support adding 3 extra .sfs files, as performance degrades as each layer added.
    #...v410 bugfix, change 6 to 7 so can have 3 sfs files.
    #...w015 change 7 to 10 so can have 6 sfs files.
   done
  fi
  #keep a record of different layer configurations...
  SAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
  SAVEFILENAMEONLY="`basename $SAVEFILE`"
  SFSFILE="`echo -n "$PUPSFS" | cut -f 3 -d ','`"
  SFSFILENAMEONLY="`basename $SFSFILE`"
  RECORDLIST="$SAVEFILENAMEONLY $SFSFILENAMEONLY $EXTRASFSLIST $ZFACTOR" #v426
  NEWUNIONRECORD="`echo "$RECORDLIST" | tr -s ' '  | sed -e 's/ $//'`"
 fi
fi

#update /etc/rc.d/BOOTCONFIG with latest unionfs layers configuration... #100222 fix...
xBOOTCONFIG="`grep -v '^PREVUNIONRECORD' $OLDFILESMNTPT/etc/rc.d/BOOTCONFIG | sed -e 's/^LASTUNIONRECORD/PREVUNIONRECORD/'`"
echo "$xBOOTCONFIG" > /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 switch_root, rc.sysinit calls rc.update, but need to do pre-cleaning...
if [ "$OLDFILESMNTPT" != "" ];then
 #an empty tmp is required for mounting a tmpfs onto later...
 rm -rf $OLDFILESMNTPT/tmp/*
 rm -rf $OLDFILESMNTPT/tmp/.[0-9a-zA-Z]*
 if [ ! -L $OLDFILESMNTPT/usr/X11R6 ];then #test if a symlink.
  #this is supposed to be a link to X11R7. <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
 rm -rf $OLDFILESMNTPT/root/tmp 2>/dev/null
 rm -f $OLDFILESMNTPT/root/.wh.tmp 2>/dev/null
 NEWPVERSION=$DISTRO_VERSION
 if [ -f $OLDFILESMNTPT/etc/puppyversion ];then
  OLDPVERSION=`cat $OLDFILESMNTPT/etc/puppyversion` #old pre-w464 installation.
  rm -f $OLDFILESMNTPT/etc/puppyversion #no longer used.
 fi
 [ -f $OLDFILESMNTPT/etc/DISTRO_SPECS ] && OLDPVERSION=`grep '^DISTRO_VERSION' $OLDFILESMNTPT/etc/DISTRO_SPECS | cut -f 2 -d '=' | cut -f 1 -d ' '` #w478

 [ ! $OLDPVERSION ] && OLDPVERSION=$NEWPVERSION
 [ "$PCLEAN" = "yes" ] && OLDPVERSION=`expr $NEWPVERSION - 1`
 [ "$PPURGE" = "yes" ] && OLDPVERSION=`expr $NEWPVERSION - 1`
 if [ $NEWPVERSION -gt $OLDPVERSION ];then
  echo -e "\\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
  mkdir $OLDFILESMNTPT/tmp/versioncleanup
  #make sure that the official boot scripts will be visible at top...
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.country
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.local0
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.modem
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.modules
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.modules2
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.network
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.shutdown
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.sysinit
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.update
  rm -f $OLDFILESMNTPT/etc/rc.d/rc.services #v405
  #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
  #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
  find ./ -noleaf -type f | sed -e 's/^\.//g' |
  while read ONENEW
  do
   DOTCNT=`expr $DOTCNT + 1`
   [ $DOTCNT -gt 100 ] && DOTCNT=0 #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
   [ -f $OLDDIR/.wh.__dir_opaque ] && rm -f $OLDDIR/.wh.__dir_opaque #v424 not needed for aufs2
   #let's get paranoid and imagine upper-directories also wiped...
   while [ ! "$OLDDIR" = "/" ];do
    OLDDIR="`dirname $OLDDIR`"
    UP1BASE="`basename $OLDDIR`"
    [ -f $OLDDIR/.wh.$UP1BASE ] && rm -f $OLDDIR/.wh.$UP1BASE
    [ -f $OLDDIR/.wh.__dir_opaque ] && rm -f $OLDDIR/.wh.__dir_opaque #v424 not needed for aufs2
   done
   #now check for 'old' files on top layer...
   if [ -f $OLDFILESMNTPT$ONENEW ];then
    #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`
    [ "$PPURGE" = "yes" ] && MODIFNEW=`expr $MODIFOLD + 1` #force overwrite all.
    if [ $MODIFNEW -ge $MODIFOLD ];then
     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
  cd /
 fi
 #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... v424 bugfixes...
  cd $OLDFILESMNTPT
  find ./ -noleaf -type f -name ".wh.*" | sed -e 's/^\.//g' |
  while read ONEOPAQUE #examples: /usr/src/.wh.__dir_opaque, /usr/src/.wh.bin
  do
   ONEDIR="`dirname $ONEOPAQUE`" #ex: /usr/src
   WHBASE="`basename $ONEOPAQUE`" #ex: .wh.bin
   if [ "$WHBASE" != ".wh.__dir_opaque" ];then #aufs2 always enter this condition...
    #example, .wh.bin alongside bin directory means it is deleted...
    ONEDEL="`echo -n "$WHBASE" | sed -e 's/^\\.wh\\.//g'`" #ex: bin
    ONEDIR="${ONEDIR}/${ONEDEL}" #ex: /usr/src/bin
    [ ! -e ".${ONEDIR}" ] && continue
   fi
   #if same dir exists lower layer, then wipe the opaque file...
   [ -d /pup_ro3${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro4${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro5${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro6${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro7${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro8${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
   [ -d /pup_ro9${ONEDIR} ] && rm -f ${OLDFILESMNTPT}${ONEOPAQUE}
  done
  cd /
 fi
 if [ $NEWPVERSION -gt $OLDPVERSION ];then
  #echo -n "$OLDPVERSION" > $OLDFILESMNTPT/etc/puppyversion #v2.14 so rc.update will run.
  vPATTERN="s%^DISTRO_VERSION=.*%DISTRO_VERSION=${OLDPVERSION}%"
  sed -e "$vPATTERN" $OLDFILESMNTPT/etc/DISTRO_SPECS > /tmp/distro_specs_old
  cp -f /tmp/distro_specs_old $OLDFILESMNTPT/etc/DISTRO_SPECS #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

[ "$RDSH" = "6" ] && exec /bin/sh >/dev/console 2>&1 #w091027

#create the unionfs layered f.s.... ***THE BIG EVENT***
if [ "$LAYERFS" = "aufs" ];then
 mount -t aufs -o udba=reval,diropq=w,dirs=${UMNTMAIN}${ZLAYER}${UMNTRO} unionfs /pup_new
else #unionfs
 UMNTMAIN="`echo -n "$UMNTMAIN" | sed -e 's/+wh//g'`" #w003 'ro+wh' not accepted by unionfs, change back to 'ro'.
 mount -t unionfs -o dirs=${UMNTMAIN}${ZLAYER}${UMNTRO} unionfs /pup_new
fi
check_status $? #END STEP FIVE
#######################END SETUP UNIONFS LAYERED FILESYSTEM###################

#######################SETUP SWITCH TO MAIN FILESYSTEM#######################
echo -n "Performing a 'switch_root' to the layered filesystem..." > /dev/console
#prepare everything for doing a switch_root...
#cpio archive does switch_root, lose the initial-ramfs, so 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_ro6
mkdir -p /pup_new/initrd/pup_ro7
mkdir -p /pup_new/initrd/pup_ro8
mkdir -p /pup_new/initrd/pup_ro9
mkdir -p /pup_new/initrd/pup_rw
mkdir -p /pup_new/initrd/pup_z
mkdir -p /pup_new/initrd/mnt
mkdir -p /pup_new/initrd/mnt/data
mkdir -p /pup_new/initrd/mnt/dev_ro1
mkdir -p /pup_new/initrd/mnt/dev_ro2
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/tmpfs2
mkdir -p /pup_new/initrd/mnt/zdrv
mkdir -p /pup_new/initrd/tmp
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

#v4.02 bring back, but allocate more space (/4 instead of /8)....
#v3.97 a problem can run out of /tmp space, remove...
#to minimise writes to pup_save and to speedup, tmpfs on /tmp...
if [ "$CREATETMPFS" != "/pup_rw" ];then #test if no tmpfs on unionfs top layer.
 ALLOCK=`expr $RAMSIZE \/ 4 + $EXTRAALLOCK`

 #v424 don't create tmpfs if have versioncleanup dir...
 #mount -t tmpfs -o size=${ALLOCK}k tmpfs /pup_new/tmp
 [ ! -e $OLDFILESMNTPT/tmp/versioncleanup ] && mount -t tmpfs -o size=${ALLOCK}k tmpfs /pup_new/tmp
 
 ##v412 bugfix, versioncleanup dir gets overwritten by this tmpfs on tmp...
 #if [ -d $OLDFILESMNTPT/tmp/versioncleanup ];then
 # cp -a $OLDFILESMNTPT/tmp/versioncleanup /pup_new/tmp/
 # [ $? -ne 0 ] && rm -rf /pup_new/tmp/versioncleanup #precaution, if tmpfs gets full.
 # rm -rf $OLDFILESMNTPT/tmp/versioncleanup
 #fi
 
 ##want var to be in the tmpfs...
 #cp -a /pup_new/var /pup_new/tmp/
 #rm -rf /pup_new/var #note, this creates a .wh.var whiteout file in pup_rw.
 #ln -snf tmp/var /pup_new/var
 #[ -d /pup_new/root/.thumbnails ] && rm -rf /pup_new/root/.thumbnails #image cache for rox.
 #mkdir /pup_new/tmp/thumbnails
 #ln -snf tmp/thumbnails /pup_new/root/.thumbnails
fi

#PNOX is a boot param. /etc/profile prevents X from starting if this file exists...
[ "$PNOX" = "yes" ] && touch /pup_new/tmp/bootcnt.txt
cp -a /DISTRO_SPECS /pup_new/initrd/

cp -af /tmp/* /pup_new/initrd/tmp/ #keep any log files.

#091122
mkdir -p /pup_new/lib/keymaps
cp -a -f /lib/keymaps/* /pup_new/lib/keymaps/
mkdir -p /pup_new/lib/consolefonts
cp -a -f /lib/consolefonts/* /pup_new/lib/consolefonts/
if [ "$KMAP" ];then #because PKEYS boot param was defined.
  echo -n "$KMAP" > /pup_new/etc/keymap
  echo -n "$FONTMAP" > /pup_new/etc/fontmap
  echo -n "$CODEPAGE" > /pup_new/etc/codepage
fi

#091225 copy exes to main f.s.
if [ -f /bin/TARGETEXES ];then
 for ONEEXE in `cat /bin/TARGETEXES` #ex: sbin/e2fsck
 do
  BASEEXE="`basename $ONEEXE`"
  [ ! -e /pup_new/$ONEEXE ] && cp -f /bin/$BASEEXE /pup_new/$ONEEXE
 done
 cp -f /bin/TARGETEXES /pup_new/bin/ #100113 puppyinstaller needs this.
fi

#RDSH is a boot param. exit to initial ramdisk shell...
if [ "$RDSH" = "yes" ];then
 echo > /dev/console
 echo "Dropped to initramfs shell. Type 'exec switch' to continue booting Puppy." > /dev/console
 exec /bin/sh >/dev/console 2>&1
fi

#v3.01 a bit untidy, but cd may still be mounted when it doesn't have to be...
case $PMEDIA in
 *cd)
  [ "$PDEV1" ] && umount /dev/$PDEV1 2>/dev/null #okay if it fails.
  ;;
esac

sync
#killall -USR1 hotplug2 #v423
umount /proc/bus/usb
umount /sys
umount /proc

#now using cpio archive for initramfs 'initial ramdisk'...
#exec switch_root -c /dev/console /pup_new /bin/busybox init 3
exec switch_root /pup_new /sbin/init

###END###
