s243a icon

remount_save.sh (draft 9)

s243a | PRO | 12/12/20 10:24:36 PM UTC (Edited) | 0 ⭐ | 1187 👁️ | Never ⏰ | []
Bash |

32.34 KB

|

None

|

0 👍

/

0 👎

#!/bin/bash
#-t --tmpfs  path to temporary save file
#-r --root   Parent directory to the new rootfs. Only applied to options which are to the right of this option.   
#-f --fake-root This is the location where the fake (or new) rootfs will be mounted. 
#-n --new-root See: -f --fake-root
#   This is a subdirectory of the -r|--root option when the -r --root option is applied to the left of this argument
unset SANDBOX_ID
unset rwbranch
unset FAKEROOT
unset SANDBOX_TMPFS
unset FAKEROOT_dir
unset SANDBOX_IMG
FAKEROOT_SET=false
#SANDBOX_ROOT=/mnt/sb
unset SANDBOX_ROOT
# [ -z "$TMPFILE" ] && TMPFILE=$(mktemp -p /tmp)
 TMPFILE=$(mktemp -p /tmp)
trap 'umountall' 1
 
 
function log(){
  local logfile="${2}"
  local trace="$3"
  #[ -z "$logfile" ] && LOGFILE 
  #[ -z "$trace" ] && trace=TRACE
  if [ ! -z "$LOGFILE" ]; then
    case "$1" in
    init)
      [ "$TRACE" = true ] && set -x
      [ ! -z "$LOGFILE" ] && rm "$LOGFILE"
      exec 6>&1           # Link file descriptor #6 with stdout.
      #exec &1> >(tee -a "$LOGFILE")
      #exec &2> >(tee -a "$LOGFILE")
      exec &> >(tee -a "$LOGFILE")
      ;;
    start)
      [ "$TRACE" = true ] && set -x
      #exec &1> >(tee -a "$LOGFILE")
      #exec &2> >(tee -a "$LOGFILE") 
      exec &> >(tee -a "$LOGFILE") 
      ;;
    stop)
      #https://stackoverflow.com/questions/21106465/restoring-stdout-and-stderr-to-default-value
      [ "$TRACE" = true ] && set +x
      exec 1>&6   #See https://tldp.org/LDP/abs/html/x17974.html
      #exec 6>&-      # Restore stdout and close file descriptor #6.
      exec &2> /dev/stderr    
      ;;
    esac
  fi    
}
 
declare -a del_rules_filter
declare -a del_rules_action
declare -a umount_rules_filter
declare -a umount_rules_action
safe_delete(){
    unset safe_delete_result
    POLICY="" #Default action if no rule is found
  if [ ! -z "$(cat /proc/mounts | grep -F "$(ls -1d $1 | sed 's:/$::')" - )" ] ||
     [ ! -z "$(cat /proc/mounts | grep -F "$(ls -1d $1 | xargs realpath )" - )" ] ; then
          #It is not safe to delete a mounted directory
          safe_delete_result=1 #This is in case one doesn't want to use the return status right away
          return 1    
  else
    PATH_TO_DEL="$(realpath -m $1)"
    [ -d "$PATH_TO_DEL" ] && "PATH_TO_DEL=$PATH_TO_DEL/"
    for a_rule_key in "${!del_rules_filter[@]}"; do
      rule_i="${a_rull_key[$a_rule_key]}"
      if [ ! -z "$(echo $PATH_TO_DEL | grep "$rule_i")" ] ||
         [[ "$PATH_TO_DEL" = $rule_i ]]; then
        action="${del_rules_action[$a_rule_key]}"
        case $action in
        DELETE)
          safe_delete_result=0 #This is in case one doesn't want to use the return status right away
          return 0
          break #This is probably redundant
          ;;
        KEEP)
          safe_delete_result=1 #This is in case one doesn't want to use the return status right away
          return 1
          break #This is probably redundant
          ;;          
        POLICY_KEEP)
          POLICY=KEEP
          ;;    
        POLICY_DELETE)
          POLICY=DELETE
          ;;    
        esac
      fi
    done
    if [ -z ${safe_delete_result+x} ]; then #If we don't have a result yet set result based on policy
      case "$POLICY" in
      KEEP)
        safe_delete_result=1
        return 1; ;; 
      DELETE)
        safe_delete_result=0
        return 0; ;;
      *)
        echo "No Delete policy set, so keeping file/dir $1"
        safe_delete_result=1
        return 1    
      esac
    fi
  fi
}
 
safe_umount(){
    unset safe_umount_result
    POLICY="" #Default action if no rule is found
    PATH_TO_UMOUNT="$(realpath -m $1)"
    [ -d "$PATH_TO_UMOUNT" ] && PATH_TO_UMOUNT="$PATH_TO_UMOUNT/" #TODO, this should always be true so add error if it is not.
 
    for a_rule_key in "${!umount_rules_filter[@]}"; do
      rule_i="${a_rull_key[$a_rule_key]}"
      if [ ! -z "$(echo $1 | grep "$rule_i")" ] ||
        [[ "$PATH_TO_UMOUNT" = $rule_i ]]; then
        action="${umount_rules_action[$a_rule_key]}"
        case $action in
        DELETE)
          safe_umount_result=0 #This is in case one doesn't want to use the return status right away
          return 0
          break #This is probably redundant
          ;;
        UMOUNT)
          safe_umount_result=1 #This is in case one doesn't want to use the return status right away
          return 1
          break #This is probably redundant
          ;;          
        POLICY_KEEP)
          POLICY=KEEP
          ;;    
        POLICY_UMOUNT)
          POLICY=UMOUNT
          ;;    
        esac
      fi
    done
    if [ -z ${safe_umount_result+x} ]; then #If we don't have a result yet set result based on policy
      case "$POLICY" in
      KEEP)
        safe_umount_result=1
        return 1; ;; 
      UMOUNT)
        safe_umount_result=0
        return 0; ;;
      *)
        echo "No Delete policy set, so keeping file/dir $1"
        safe_umount_result=1
        return 1    
      esac
    fi
  
}
umountall() {
  {
  log start
  set -x
  #R_FR=$(realpath -m "$FAKEROOT")
  #[ ${#R_FR} -lt 2 ] && exit
  safe_umount $SANDBOX_TMPFS
  [ $safe_umount_result -eq 0 ] && umount -l $SANDBOX_TMPFS
  if [ PUPMODE = 2 ]; then #Full Install
      safe_umount $FAKEROOT/tmp
      umount -l $FAKEROOT/tmp
    else
      safe_umount $FAKEROOT/initrd/mnt/tmpfs
      [ $safe_umount_result -eq 0 ] && umount -l $FAKEROOT/initrd/mnt/tmpfs
    fi
  for layer_name in "pup_ro2" "pup_ro3" "pup_ro4" "pup_ro5" "pup_z"; do
    layer="$(eval 'echo $'$layer_name)"
    if [ ! -z "$layer" ] ; then
      safe_umount "$FAKEROOT/initrd/$layer_name"
      [ $safe_umount_result -eq 0 ] && umount -l "$FAKEROOT/initrd/$layer_name"
    fi
  done 
  for aFolder in /proc /sys /dev ""; do
     safe_umount $FAKEROOT"/$aFolder"
     [ $safe_umount_result -eq 0 ] && umount -l $FAKEROOT$aFolder
  done
  
  
  if [ -z "$RW_LAYER" ]; then
    safe_umount "$SANDBOX_TMPFS"
    [ $safe_umount_result -eq 0 ] && umount -l $SANDBOX_TMPFS
    safe_delete "$SANDBOX_TMPFS"
    [ $safe_delete_result -eq 0 ] && rmdir $SANDBOX_TMPFS
  fi
  
  safe_delete $FAKEROOT
  [ $safe_delete_result -eq 0 ] && rmdir $FAKEROOT
 
  } # 2> /dev/null
}
 
function choose_save(){
    # location not specified - then ask
    log stop
    dialog --backtitle "rw image sandbox" --title "choose rw image" \
    --extra-button --extra-label "Create" --ok-label "Locate" \
    --yesno "You didn't specify the location of the rw image file. Do you want to locate existing file, or do you want to create a new one?" 0 0
    chosen=$?
    log start
    case $chosen in
        0) # ok - locate
            log stop
            dialog --backtitle "rw image sandbox" --title "Specify location of existing rw image" --fselect `pwd` 8 60 2> $TMPFILE
            savebranch=`cat $TMPFILE`
            log start
            rm $TMPFILE
            if [ -n "$savebranch" ]; then
                if [ -d "$savebranch" ]; then
                  case "$savebranch" in
                  "/mnt"|"/mnt/"|"/mnt/home"|"/mnt/home/"|"/")
                    log stop
                    echo "warning chose the following savebranch $savebranch"
                    read -p "Press enter to continue"
                    log start
                    set_sandbox_img ""
                    ;;
                  esac
                  SANDBOX_IMG=$savebranch
                elif [ ! -f "$savebranch" ]; then
                    echo "$savebranch doesn't exist - exiting."
                    echo "will use tmpfs instead"
                    log stop
                    read -p "Press enter to continue"
                    log start
                    savebranch=""
                else
                  set_sandbox_img ""                    
                fi
            else
                echo "You didn't specify any file or you pressed cancel. Exiting."
                exit
            fi
            ;;
        3) # create
            echo "create"
            log stop
            dialog --backtitle "save image sandbox" --title "Specify name and path of new the file" --fselect `pwd` 8 60 2> $TMPFILE
            savebranch=`cat $TMPFILE`
            log start
            rm $TMPFILE
            if [ -n "$savebranch" ]; then
                if [ -f "$savebranch" ]; then
                    echo "$savebranch already exist - exiting."
                    exit
                else
                    # get the size
                    log stop
                    dialog --title "Create new save image" --inputbox "Specify size (in megabytes)" 0 40 100 2> $TMPFILE
                    size=`cat $TMPFILE`
                    log start
                    rm $TMPFILE
                    
                    if [ -n "$size" ]; then
                        if dd if=/dev/zero of="$savebranch" bs=1 count=0 seek="$size"M; then
                            if ! mke2fs -F "$savebranch"; then
                                echo "I fail to make an ext2 filesystem at $savebranch, exiting."
                                exit
                            fi
                        else
                            echo "I fail to create a ${size}M file at $savebranch,, exiting."
                            exit
                        fi
                    else
                        echo "You didn't specify the size or your press cancel. Exiting."
                        exit
                    fi                  
                fi
            else
                echo "You didn't specify any file or you pressed cancel. Exiting."
                exit
            fi
            ;;
        1 | 255) # 1 is cancel, 255 is Escape
            ;&
        *) # invalid input - treat as cancel
            echo "Cancelled - exiting."
            exit
            ;;
    esac
}
function find_save(){
  if [ ! -z "SANDBOX_IMG" ]; then
    FULL_SAVE_PATH=$SANDBOX_IMG
  else 
   
    for prefix in '${DISTRO_FILE_PREFIX}save' '.*save'; do
      for dir in "$PDRV/${PSUBDIR}" "PDRV";  do
       
        ONE_SAVE="$(ls $dir -1 | grep -m "${prefix}save")"
        if [ -z "$ONE_SAVE" ]; then
           continue
        else
           SAVE_FILE="$ONE_SAVE"
           FULL_SAVE_PATH="$dir"/ONE_SAVE
           break
        fi
      done
     done
     echo "PSAVE"mount_items
   fi
}
function find_bk_folders(){
  for a_PDRV in "$PDRV" sr0 sr1; do #Consider adding /mnt/home here
    for a_psubdir in "${PSUBDIR}" "";  do
      MT_PT_of_Folder="$(mount_fn2 "$PDRV" "${PSUBDIR}")"
      #https://github.com/puppylinux-woof-CE/woof-CE/blob/c483d010a8402c5a1711517c2dce782b3551a0b8/initrd-progs/0initrd/init#L981
      BKFOLDERS="$(find $MT_PT_of_Folder -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]' | sed -e s%^${SAVE_MP}/%% | sort -r)"
      [ ! -z "#BKFOLDERS" ] && break   
    done
  done
}
 
function mk_initrd_dir(){
  mkdir -p "$FAKEROOT"/initrd
  if [ -z "$PUPMODE" ] ; then
    if [ -z "$PMEDIA" ]; then
      #if [ "$PUPMODE" = 5 ] ; then
      #  #aufs layers:              RW (top)      RO1             RO2              PUPMODE
      #  #First boot (or pfix=ram): tmpfs                         pup_xxx.sfs      5
      PUPMODE=5 #MAYBE PUPMODE=2 would be better
    elif [ PMEDIA = 'atahd' ] || [ "$PMEDIA" = 'usbhd' ]; then
      find_save
      if [ -f "$FULL_SAVE_PATH" ] || [ -d "$FULL_SAVE_PATH" ]; then
        #aufs layers:               RW (top)      RO1             RO2              PUPMODE
        #Normal running puppy:      pup_save.3fs                  pup_xxx.sfs      12      
        PUPMODE=12
      else
        echo "Invalid SAVE_PATH=$SAVE_PATH does not exist"
        PUMPMODE=2
        #TODO, prompt to either search for save file/folder or alternatively create it. 
      fi
    elif [ PMEDIA = 'usbflash' ] || [ pmedia = 'ideflash' ]; then
      find_save
      #aufs layers:                 RW (top)      RO1             RO2              PUPMODE
      #ditto, but flash drive:      tmpfs         pup_save.3fs    pup_xxx.sfs      13
      if [ -f "$SAVE_PATH" ] || [ -d "$SAVE_PATH" ]; then
        #aufs layers:               RW (top)      RO1             RO2              PUPMODE
        #ditto, but flash drive:    tmpfs         pup_save.3fs    pup_xxx.sfs      13
        PUPMODE=13
      else
        echo "Invalid SAVE_PATH=$SAVE_PATH does not exist"
        PUPMODE=5
      fi
    elif [ "$PMEDIA" =  usbcd ] || [ "$PMEDIA" =  idecd ] || [ "$PMEDIA" =  satacd ] ; then 
      find_bk_folders
      if [ ! -z "$BKFOLDERS" ]; then
        PUPMODE=77  #MULTI-Session CD
      else #First Boot
        find_save
        if [ -f "$FULL_SAVE_PATH" ] || [ -d "$FULL_SAVE_PATH" ]; then
          PUPMODE=13      
        else
          PUPMODE=5
        fi
      fi
      #aufs layers:            RW (top)      RO1             RO2              PUPMODE
      #Multisession cd/dvd:       tmpfs         folders         pup_xxx.sfs      77
    else #[PUPMODE=2 -> full install
      PUPMODE=2
    fi
    if [ "$PUPMODE" = 2 ] && [ 1 -ne 1 ]; then #Full install
      echo "Full install has no initrd"
    else
      mkdir -p "$FAKEROOT/initrd"
      cd $FAKEROOT/initrd
      if [ "$PUPMODE" = 12 ]; then # Usually [ PMEDIA = 'atahd' ] || [ "$PMEDIA" = usbhd ] 
        ln -s mnt/dev_save/"${SAVE_PATH}" pup_rw
      elif [ "$PUPMODE" = 13 ] || [ "$PUPMODE" = 5 ] || [ "$PUPMODE" = 77 ]; then 
        ln -s mnt/tmpfs/pup_rw pup_rw
        if [ "$PUPMODE" = 13 ]; then  # Usually [ PMEDIA = 'usbflash' ] || [ pmedia = 'ideflash' ]
          ln -s "mnt/tmpfs/dev_save/${SAVE_PATH}" pup_ro1
        elif [ "$PUPMODE" = 77 ]; then
          ln -s mnt/tmpfs/pup_ro1/"${SAVE_PATH}" pup_ro1  #Usually [ "$PMEDIA" =  usbcd ] || [ "$PMEDIA" =  idecd ] || [ "$PMEDIA" =  satacd ] 
        fi
      fi
      mkdir -p "$FAKEROOT/initrd/mnt/dev_save"
      mount -o bind  /mnt/home "$FAKEROOT/initrd/mnt/dev_save"
      mkdir $FAKEROOT/mnt
      cd $FAKEROOT/mnt
      ln -s ../initrd/mnt/dev_save
      cd $FAKEROOT
      mount -o bind $SANDBOX_IMG initrd/mnt/tmpfs/pup_rw #not sure if this applies to all pupmodes. 
      
    fi
  fi
}
 
function set_fakeroot(){
    unset CLEANUP_SANDBOX_ROOT
    # if SANDBOX_ROOT is set to null then set it in this function
    # if FAKEROOT is null then this implies "/"
    if [ -z ${FAKEROOT+x} ] && [ $FAKEROOT_SET = false ]; then 
      FAKEROOT=fakeroot
      CLEANUP_SANDBOX_ROOT=yes
    fi
    if [ ! -z ${SANDBOX_ROOT+x} ] || [ ${#FAKEROOT} -gt 1 ]; then 
       
      if [ "${CLEANUP_SANDBOX_ROOT}" = yes ]; then
        SANDBOX_ROOT=/mnt/sb
      else
        FAKEROOT_SET
      fi    
      
 
      if [ ${#SANDBOX_ROOT} -gt 1 ] && [ $FAKEROOT_SET = false ]; then
        FAKEROOT=$SANDBOX_ROOT/$FAKEROOT
        FAKEROOT_SET=true
      elif [ ! -z ${FAKEROOT+x} ]; then
        FAKEROOT_SET=true
      fi
       FAKEROOT_dir="${FAKEROOT%/*}"
      [ -z "${SANDBOX_ROOT}" ] && SANDBOX_ROOT=${FAKEROOT_dir}
      if grep -q $FAKEROOT /proc/mounts; then
        if [ ! "$SANDBOX_ROOT" = /mnt/sb ]; then
            log stop
            dialog --backtitle "rename root" --title "already mounted" \
            --extra-button --extra-label "Rename" --ok-label "Keep" \
            --yesno "FAKEROOTI is already a mount point. Rename Root?" 0 0
            chosen=$?
            log start      
           case "#chosen" in
           1)
             RENAME_ROOT=yes; ;;
           0)
             RENAME_ROOT=no; ;;
           esac
           
        else
          RENAME_ROOT=yes
        fi  
        
        if [ "${RENAME_ROOT}" = yes ]; then     
          FAKEROOT=$(mktemp -d -p ${FAKEROOT%/*}/ ${FAKEROOT##*/}.XXXXXXX)
          SANDBOX_ID=".${FAKEROOT##*.}"
          if [ -z "$SANDBOX_IMG" ]; then
            [ -z "$savebranch" ] && choose_save
            savebranch="$(realpath -m $savebranch)"
            if [ -d  "$savebranch" ]; then
              #TODO: verify this works if savebranch is a mounted directory.
              SANDBOX_IMG="$savebranch"
            else
              [ ! -z "$savebranch"  ] && loop=$(losetup-FULL -a | grep  "$savebranch"  | sed "s/:.*$//" )
              if [ ! -z "$loop" ]; then
                SANDBOX_IMG=$(cat /proc/mounts | grep $loop | cut -d " " -f2)
              fi
              if [ -z "$SANDBOX_IMG" ] ; then
                SANDBOX_IMG=$FAKEROOT_dir/sandbox_img${SANDBOX_ID}
                mkdir -p $SANDBOX_IMG
              fi
            fi
            rmdir $FAKEROOT
          else
            log stop
            echo "Warning chose to remount over existing mount! $FAKEROOT"
            echo "ctrl-c to quote"
            read -p "Press enter to continue"  
            log start     
          fi
        fi
      else
            echo "This is our first sandbox"
      fi
    else
      echo "Warning sandbox root not defined" 
      #[ -z "$FAKEROOT" ] && FAKEROOT=/
    fi
    if [ $CLEANUP_SANDBOX_ROOT = yes ]; then
      if [ ${#del_rules_filter} -eq 0 ]; then
         del_rules_filter+=( $SANDBOX_ROOT"/*" )
         del_rules_filter+=( POLICY_DELETE )
      fi
      if [ ${#umount_rules_filter} -eq 0 ]; then
         umount_rules_filter+=( $SANDBOX_ROOT"/*" )
         umount_rules_filter+=( POLICY_UMOUNT )
      fi    
    fi
    mkdir -p "$SANDBOX_ROOT"
    mkdir -p "$FAKEROOT"
}
function set_sandbox_img(){
     [ -z ${FAKEROOT_dir+x} ] &&  set_fakeroot
     if [ ! -z ${SANDBOX_IMG+x} ]  && [ -z "${SANDBOX_IMG}" ] || [ ! -z ${1+x} ]; then
      SANDBOX_IMG=sandbox_img
      SANDBOX_IMG=${SANDBOX_IMG}${SANDBOX_ID}
      [ ! -z "$FAKEROOT_dir" ] && SANDBOX_IMG=$FAKEROOT_dir/$SANDBOX_IMG
     elif [ -z "${FAKEROOT_dir}" ] ; then 
      SANDBOX_IMG=$FAKEROOT_dir/$SANDBOX_IMG
     fi
}
function set_sandbox_tmpfs(){
     [ -z ${FAKEROOT_dir+x} ] &&  set_fakeroot
     if [ ! -z ${SANDBOX_TMPFS+x} ]  && [ -z "${SANDBOX_TMPFS}" ]; then
      SANDBOX_TMPFS=sandbox_tmpfs
      SANDBOX_TMPFS=${SANDBOX_TMPFS}${SANDBOX_ID}
      [ -z "$FAKEROOT_dir" ] && SANDBOX_TMPFS=$FAKEROOT_dir/$SANDBOX_TMPFS
    elif [ -z "${FAKEROOT_dir}" ] ; then 
      SANDBOX_TMPFS=$FAKEROOT_dir/$SANDBOX_TMPFS
    fi
}
declare -a options="$(getopt -o t::,r::,s:,d:,l: --long input-file:tmpfs::,root::,save:,pupmode::,pmedia:,pdrv:,psubdir:,distro-specs:,logfile:,trace: -- "$@")"
eval set --"$options"
while [ $# -gt 0 ]; do
  case "$1" in
  -t|--tmpfs)
    if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
      SANDBOX_TMPFS="$2"
      set_sandbox_tmpfs
      shift 2
    else
      SANDBOX_TMPFS="" #Later we use [ -z ${SANDBOX_TMPFS+x} ] to check that this is set
      set_sandbox_tmpfs
      shift 1
    fi; ;;
   -r|--root)
    if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
      SANDBOX_ROOT="$2"
      shift 2
    else
      SANDBOX_ROOT="" #Later we use [ -z ${SANDBOX_ROOT+x} ] to check that this is set
      shift 1
    fi; ;;   
   -f|-n|--fake-root|--new-root)
      if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
        FAKEROOT="$2"
        set_fakeroot
        shift 2
      else
        FAKEROOT="" #Later we use [ -z ${FAKEROOT+x} ] to check that this is set
        set_fakeroot
        shift 1
      fi; ;;  
   -s|--save) #$SANDBOX_IMG
    #if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
      if [ -d "$2" ]; then
        SANDBOX_IMG=$2
        savebranch=$2
      else [ -f "$2" ]
        #mnt_sb_immage
        #mount -o loop "$rwbranch" $SANDBOX_IMG;
        savebranch=$1
        loop=$(losetup-FULL -a | grep  "$savebranch"  | sed "s/:.*$//")
        if [ ! -z "$loop" ]; then
          SANDBOX_IMG=$(/proc/mounts | grep $loop | cut -d " " -f2)
        else
          SANDBOX_IMG=""
          set_sandbox_img
        fi
        shift 2;
      fi; ;;
    --pupmode)
      if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
        PUPMODE=$2
        shift 2
      else
        PUPMODE=2
        shift
      fi
    ;;
  --pmedia) PMEDIA=$2; shift 2; ;;
  -d| --pdrv) PDRV=$2; shift 2; ;;
  --psubdir) PSUBDIR=$2; 
    shift 2; ;; 
  --distro-specs) 
     DISTRO_SPECS=$2; 
     . "$DISTRO_SPECS"
     shift 2 
     ;;
  -l|--logfile)
    LOGFILE=$2
    [ -z "$TRACE" ] && TRACE=true
    shift 2
    log init
    ;;  
  -t|--trace)
    TRACE=$2
    if [ $# -gt 1 ] && [[ ! "$2" = --* ]] && [ ! -z "$2" ]; then
      TRACE="$2"
      shift 2
    else
      TRACE=true
      shift 1
    fi
    log init
    ;; 
   --) 
    shift 1
    options2+=( "$@" )
    break; ;;
  *)
     options2+=( "$1" )
     shift 1; ;;
    
  esac
done
if [ -z ${SANDBOX_ROOT+x} ] && [ -z ${FAKEROOT+x} ]; then
  SANDBOX_ROOT="" #Later this will change to SANDBOX_ROOT=/mnt/sb
  set_fakeroot
  [ -z $SANDBOX_IMG ] && set_sandbox_img
fi 
 
 
 
#SANDBOX_TMPFS=$SANDBOX_ROOT/sandbox # mounted rw location of 
#SANDBOX_TMPFS=$SANDBOX_ROOT/initrd/mnt/tmpfs/pup_rw
#tmpfs used for sandbox
#SANDBOX_ID=
TMPFILE=$(mktemp -p /tmp)
# use namespaces if available
#[ -e /proc/1/ns/pid ] && [ -e /proc/1/ns/mnt ] && type unshare >/dev/null && USE_NS=1
 
# umount all if we are accidentally killed
#trap 'umountall' 1
#s243a don't unmount on error
 
# 0.1 must be root
if [ $(id -u) -ne 0 ]; then
    echo "You must be root to use sandbox."
    exit
fi
 
## 0.2 cannot launch sandbox within sandbox
#if [ "$AUFS_ROOT_ID" != "" ] ; then
#   grep -q $SANDBOX_ROOT /sys/fs/aufs/$AUFS_ROOT_ID/br0 &&
#       echo "Cannot launch sandbox within sandbox." && exit
#fi
# s243a we are remounting everything rather then creating a sandbox.
 
# 0.3 help
case "$1" in
    --help|-h)
    echo "Usage: ${0##*/}"
    echo "Starts an in-memory (throwaway) sandbox. Type 'exit' to leave."
    exit
esac
 
## 0.4 if not running from terminal but in Xorg, then launch via terminal
#! [ -t 0 ] && [ -n "$DISPLAY" ] && exec $XTERM -e "$0" "$@"
#! [ -t 0 ] && exit
 
## 0.5 is this the first sandbox? If not, then create another name for mountpoints
#if grep -q $FAKEROOT /proc/mounts; then
#   FAKEROOT=$(mktemp -d -p $SANDBOX_ROOT ${FAKEROOT##*/}.XXXXXXX)
#   SANDBOX_ID=".${FAKEROOT##*.}"
#   SANDBOX_TMPFS=$SANDBOX_ROOT/${SANDBOX_TMPFS##*/}${SANDBOX_ID}
#   rmdir $FAKEROOT
#fi
 
# 1. get aufs system-id for the root filesystem
if [ -z "$AUFS_ROOT_ID" ] ; then
    AUFS_ROOT_ID=$(
        awk '{ if ($2 == "/" && $3 == "aufs") { match($4,/si=[0-9a-f]*/); print "si_" substr($4,RSTART+3,RLENGTH-3) } }' /proc/mounts
    )
fi
 
# 2. get branches, then map branches to mount types or loop devices 
items=$(
{ echo ==mount==; cat /proc/mounts; 
  echo ==losetup==; losetup-FULL -a; 
  echo ==branches==; ls -v /sys/fs/aufs/$AUFS_ROOT_ID/br[0-9]* | xargs sed 's/=.*//'; } | \
  awk '
  /==mount==/ { mode=1 }
  /==losetup==/ { mode=2 }
  /==branches==/ { mode=3 }
  {
    if (mode == 1) {
        # get list of mount points, types, and devices - index is $3 (mount points)
        mountdev[$2]=$1
        mounttypes[$2]=$3
    } else if (mode == 2) {
        # get list of loop devices and files - index is $1 (loop devs)
        sub(/:/,"",$1)
        sub(/.*\//,"",$3); sub(/)/,"",$3)
        loopdev[$1]=$3
    } else if (mode == 3) {
        # map mount types to loop files if mount devices is a loop
        for (m in mountdev) {
            if ( loopdev[mountdev[m]] != "" ) mounttypes[m]=loopdev[mountdev[m]]
        }
        # for (m in mountdev) print m " on " mountdev[m] " type " mounttypes[m]
        mode=4
    } else if (mode==4) {
        # print the branches and its mappings
        if ($0 in mounttypes){
          print $0, mounttypes[$0], "on"
        }
        else {
            MNT_PATH=$0
            sub(/^.*[\/]/,"")
            print MNT_PATH, $0, "on"
        }
    }
  }  
'
)
# '
 
# 3. Ask user to choose the SFS
log stop
dialog --separate-output --backtitle "tmpfs sandbox" --title "sandbox config" \
    --checklist "Choose which SFS you want to use" 0 0 0 $items 2> $TMPFILE
chosen="$(cat $TMPFILE)"
log start
clear
if [ -z "$chosen" ]; then
    echo "Cancelled or no SFS is chosen - exiting."
    exit 1
fi
 
# 4. convert chosen SFS to robranches
robranches=""
for a in $(cat $TMPFILE) ; do
    robranches=$robranches:$a=ro
done
rm $TMPFILE
 
# 5. get location of rw image
[ -z ${savebranch+x} ] && choose_save
mkdir -p $SANDBOX_IMG
[ ${#SANDBOX_IMG} -gt 1 ] || echo "Pathlenth too short SANDBOX_IMG='$SANDBOX_IMG'"
if [ ! -z "$savebranch"  ]; then
  if [ -f "$savebranch" ]; then
        loop=$(losetup-FULL -a | grep  "$savebranch"  | sed "s/:.*$//" )
        if [ ! -z "$loop" ]; then
          SANDBOX_IMG=$(cat /proc/mounts | grep $loop | cut -d " " -f2)
        else
          mount -o loop "$savebranch" $SANDBOX_IMG
        fi
  fi
fi
#[ ${#SANDBOX_IMG} -gt 1 ] || echo "Pathlenth too short SANDBOX_IMG='$SANDBOX_IMG'"
#if  [ -z "$rwdir" ] ; then  #savebranch
  if [ ! -z "$PUPMODE" ]; then
    if [ $PUPMODE  -ne 5 ] && [ $PUPMODE  -ne 13 ] && [ $PUPMODE  -ne 77 ]; then
      if  [ -z ${SANDBOX_TMPFS+x} ]; then
        SANDBOX_TMPFS="" #Later we use [ -z ${SANDBOX_TMPFS+x} ] to check that this is set
      fi
    fi
  fi
#fi
# # 4. make the mountpoints if not exist  yet
# if [ ! -z "$SANDBOX_IMG" ]; then
# mkdir -p $SANDBOX_IMG
# mount -o loop "$savebranch" $SANDBOX_IMG || {
#     echo "Failed to mount '$savebranch' at '$SANDBOX_IMG'"
#     exit
# } 
#fi
if [ ! -z "$SANDBOX_ROOT" ]; then
  DEV_SAVE=$SANDBOX_ROOT/dev_save
  mkdir -p "$DEV_SAVE"
  if [ -z "$PDRV" ]; then
    if [[ "$SANDBOX_IMG" = *"/mnt/"* ]]; then
      PSUBDIR=${SANDBOX_IMG#/mnt/*/}
      PDRV=${SANDBOX_IMG%"/$PSUBDIR"}
      PDRV_real=$(cat /proc/mounts | grep $(realpath $PDRV) | cut -d " " -f1)
          PSUBDIR_i=${PSUBDIR}
          PDRV_i=${PDRV}
          PDRV_real_i=${PDRV_real}      
      while (true); do
 
          if [[ PDRV_real_i = /dev/loop* ]]; then
            PDRV_real_i=$(losetup-FULL -a | grep "$(basename PDRV_real)")
            PDRV_real_i=${PDRV_real#*(}
            PDRV_real_i=${PDRV_real%)}
            PSUBDIR_i=${PDRV_real_i#/mnt/*/}
            PDRV_real=$PSUBDIR_i/$PDRV_real
            PDRV_real_i=${SANDBOX_IMG%"/$PSUBDIR_i"}
            PDRV_real_i=$(cat /proc/mounts | grep $(realpath $PDRV_real_i) | cut -d " " -f1)
          elif [[ PDRV_real_i = /dev/* ]]; then
            PDRV_real=$(blkid | grep $PDRV_real)
            break
          else
            echo "could not identify PDRV_real"
            break
          fi
          
      done
    fi
  fi
fi
#if [ -z $PDRV ]; then
#  case "$(uname -a)"
#fi
[ -z $PDRV ] && PDRV=/mnt/home
if [ -z  "$SANDBOX_IMG" ] || [ ! -z ${SANDBOX_TMPFS+x} ]; then 
  if [ -z "$SANDBOX_TMPFS" ] ; then
    #SANDBOX_TMPFS=$SANDBOX_ROOT/sandbox
    set_sandbox_tmpfs
    
    #if grep -q $SANDBOX_TMPFS /proc/mounts; then
    #  #FAKEROOT=$(mktemp -d -p $SANDBOX_ROOT ${FAKEROOT##*/}.XXXXXXX)
    #  #SANDBOX_ID=".${FAKEROOT##*.}"
    #  SANDBOX_TMPFS=$SANDBOX_ROOT/${SANDBOX_ID/}${SANDBOX_ID}
    #  mkdir -p -f SANDBOX_TMPFS
    #  mount -t tmpfs none $SANDBOX_TMPFS; #We could exit if this fails but we don't need to becuase we can still write to SANDBOX_TMPFS even if it isn't tmpfs.
    #  rmdir $FAKEROOT
    #fi
  fi
  
  if [ ! -z "${SANDBOX_TMPFS}" ] && [ ! -z "$(grep -q ${SANDBOX_TMPFS} /proc/mounts)" ]; then
    mount -t tmpfs none $SANDBOX_TMPFS;
  fi
elif [ ! -z "${SANDBOX_TMPFS}" ]; then
  if [ ! -z "${SANDBOX_TMPFS}" ] && [ ! -z "$(grep -q ${SANDBOX_TMPFS} /proc/mounts)" ]; then
    mount -t tmpfs none $SANDBOX_TMPFS;
  fi 
fi
if [ -z "$SANDBOX_TMPFS" ]; then 
  SANDBOX_TMPFS=$SANDBOX_IMG
else
  if [ $robranches ~= ** ]; then
    robranches=$SANDBOX_IMG=rr:$robranches
  fi
fi
mkdir -p $FAKEROOT
 
#mk_initrd_dir
 
# 5. do the magic - mount the rw image first, and then the rest with aufs
#if mount -o loop "$rwbranch" $SANDBOX_IMG; then
if [ ${#FAKEROOT} -gt 1 ] && ! grep -q $FAKEROOT /proc/mounts; then
 
 
  echo "mount -t aufs -o \"br:$SANDBOX_TMPFS=rw$robranches\" aufs ${FAKEROOT}"
  echo "About to mount FAKEROOT at $FAKEROOT"
  read -p "Press enter to continue"
  
    mount -t aufs -o "br:$SANDBOX_TMPFS=rw$robranches" aufs ${FAKEROOT}
 
        # 5. record our new aufs-root-id so tools don't hack real filesystem
        SANDBOX_AUFS_ID=$(grep $FAKEROOT /proc/mounts | sed 's/.*si=/si_/; s/ .*//') #'
        sed -i -e '/AUFS_ROOT_ID/ d' $FAKEROOT/etc/BOOTSTATE 2> /dev/null
        echo AUFS_ROOT_ID=$SANDBOX_AUFS_ID >> $FAKEROOT/etc/BOOTSTATE  
    
    
    # 7. sandbox is ready, now just need to mount other supports - pts, proc, sysfs, usb and tmp    
    
    mkdir -p $FAKEROOT/dev $FAKEROOT/sys $FAKEROOT/proc $FAKEROOT/tmp
    mkdir -p  "$DEV_SAVE/${PSUBDIR}"
    mount -o bind  "$PDRV/${PSUBDIR}" "$DEV_SAVE/${PSUBDIR}"
    
    #mount -o bind  "$DEV_SAVE/${PSUBDIR}" "$FAKEROOT/initrd/mnt/dev_save"
    mount -o bind  "$DEV_SAVE" "$FAKEROOT/initrd/mnt/dev_save"
 
    #Maybe optionally do this based on some input paramater:
    #Also pull these layers from an array
    for layer_name in "pup_ro2" "pup_ro3" "pup_ro4" "pup_ro5" "pup_z"; do
        layer="$(eval 'echo $'$layer_name)"
      if [ ! -z "$layer" ] ; then
        mount -o bind  "$layer" "$FAKEROOT/initrd/$layer_name"
      fi
    done
 
    case "$(uname -a)" in
    *fatdog*)
      mkdir -p "$FAKEROOT/aufs"
      #mount -o bind  "$DEV_SAVE/${PSUBDIR}" "$FAKEROOT/aufs/dev_save"
      mkdir -p "$FAKEROOT/aufs/dev_save"
      mount -o bind  /mnt/home "$FAKEROOT/aufs/dev_save"
      cd $FAKEROOT
      #mkdir -p mnt/home
      cd mnt
      ln -s home ../aufs/dev_save
      pup_save="$SANDBOX_IMG" 
      mount -o bind  "$pup_save" "$FAKEROOT/aufs/pup_save"
      base_sfs=/aufs/pup_ro
      mount -o bind  "$base_sfs" "$FAKEROOT/aufs/pup_ro"
      if [ "$SANDBOX_TMPFS" != "$SANDBOX_IMG" ]; then
         pup_rw="$SANDBOX_TMPFS"
         mount -o bind  "$pup_rw" "$FAKEROOT/aufs/pup_rw"
      fi
      ;;    
    *) #assume this is puppy
      mk_initrd_dir
      #mkdir -p "$FAKEROOT/initrd/mnt/dev_save"
      #mount -o bind  /mnt/home "$FAKEROOT/initrd/mnt/dev_save"
      #mkdir $FAKEROOT/mnt
      #cd $FAKEROOT/mnt
      #ln -s ../initrd/mnt/dev_save
      ;;
    esac
    mkdir -p $FAKEROOT/mnt/home
    mount -o rbind /dev $FAKEROOT/dev
    mount -t sysfs none $FAKEROOT/sys
    mount -t proc none $FAKEROOT/proc
    if [ PUPMODE = 2 ] || [[ "$(uname -a)" = *fatdog* ]]; then #Full Install #Maybe don't base this on PUPMODE
      tmp_des=$FAKEROOT/tmp
      tmp_source=/tmp
    else
      #case "$(uname -a)" in 
      #*fadog*)
      #
      #*) #assume this is puppy
        mkdir -p $FAKEROOT/initrd/mnt/tmpfs
        tmp_des=$FAKEROOT/initrd/mnt/tmpfs
        tmp_source=/initrd/mnt/tmpfs
        cd $FAKEROOT
      rm tmp
      ln -s initrd/mnt/tmpfs tmp
    fi
    mount -o bind $tmp_source $tmp_des
 
    cd $FAKEROOT
    case "$(uname -a)" in
    *fatdog*)
      mkdir -p $FAKEROOT/aufs
      mount -o bind $SANDBOX_TMPFS $FAKEROOT/$SANDBOX_TMPFS
      ;;
    *) #assume this is puppy
      mk_initrd_dir
      #ln -s initrd/mnt/tmpfs tmp   
      #mkdir -p $FAKEROOT/$SANDBOX_TMPFS
      #mount -o bind $SANDBOX_TMPFS $FAKEROOT/$SANDBOX_TMPFS # so we can access it within sandbox
      ;;
    esac
 
#    #mkdir -p $FAKEROOT/$SANDBOX_TMPFS
#    mkdir -p $FAKEROOT/$SANDBOX_IMG
#    mount -o bind $SANDBOX_IMG $FAKEROOT/$SANDBOX_IMG  # so we can access it within sandbox    
     cp /usr/share/sandbox/* $FAKEROOT/usr/bin 2> /dev/null
    
 
 
        # 8. optional copy, to enable running sandbox-ed xwin 
        cp /usr/share/sandbox/* $FAKEROOT/usr/bin 2> /dev/null
        
        # 9. make sure we identify ourself as in sandbox - and we're good to go!
        echo -e '\nexport PS1="sandbox'${SANDBOX_ID}'# "' >> $FAKEROOT/etc/shinit #fatdog 600
        sed -i -e '/^PS1/ s/^.*$/PS1="sandbox'${SANDBOX_ID}'# "/' $FAKEROOT/etc/profile # earlier fatdog
        
    if [ -d "$FULL_SAVE_PATH" ]; then #TODO verify that this works with a save file
      if [ $PUPMODE -eq 13 ] && [ $PUPMODE -eq 77 ]; then
        #TODO: when PUPMODE=77 (multisession cd) we need to copy folders. See: https://github.com/puppylinux-woof-CE/woof-CE/blob/c483d010a8402c5a1711517c2dce782b3551a0b8/initrd-progs/0initrd/init#L1084
        #and copy_folders()  https://github.com/puppylinux-woof-CE/woof-CE/blob/c483d010a8402c5a1711517c2dce782b3551a0b8/initrd-progs/0initrd/init#L482
          #https://github.com/puppylinux-woof-CE/woof-CE/blob/c483d010a8402c5a1711517c2dce782b3551a0b8/initrd-progs/0initrd/init#L1091
          mount -o remount,prepend:"$FULL_SAVE_PATH"=rw,mod:"$SANDBOX_TMPFS"=ro,del:"$SANDBOX_TMPFS" "$FAKEROOT" 
          #mount -o remount,add:1:"$FULL_SAVE_PATH"=ro+wh "$FAKEROOT" 
      fi
    fi
        
        
        echo "Starting sandbox now."
        log stop 
        if [ $USE_NS ]; then
            unshare -f -p --mount-proc=$FAKEROOT/proc chroot $FAKEROOT
        else
            chroot $FAKEROOT
        fi
        log start
        # 8. done - clean up everything 
        umountall
        echo "Leaving sandbox."  
    
elif [ "${FAKEROOT:-/}" = "/" ]; then
  #[ -z "$FAKEROOT" ] &&  $FAKEROOT="/"
  echo "mount -t aufs -o \"remount,br:$SANDBOX_TMPFS=rw$robranches\" aufs  ${FAKEROOT:-/}"
  echo "Warning!  about to remount rootfs at $FAKEROOT"
  read -p "Press enter to continue"
  trap - 1 #Clear traps
  trap
  mount -t aufs -o "br:$SANDBOX_TMPFS=rw$robranches" aufs ${FAKEROOT:-/};
  mkdir -p /dev /sys /proc /tmp #These probably already exist
  [[ "`mountpoint /dev`"  != *"is a mountpoint"* ]] && mount -t devtmpfs devtmpfs /dev
  mkdir -p /initrd/mnt/tmpfs
  [[ "`mountpoint /initrd/mnt/tmpfs`"  != *"is a mountpoint"* ]] && mount -t tmpfs none /initrd/mnt/tmpfs
  mkdir -p /initrd/mnt/tmpfs/tmp
  if [[ "`mountpoint /tmp`"  != *"is a mountpoint"* ]]; then
    if [[ "`mountpoint /initrd/mnt/tmpfs`"  != *"is a mountpoint"* ]]; then
      mount -o bind /initrd/mnt/tmpfs/tmp /tmp
    else
      mount -t tmpfs none /tmp
    fi
  fi
else
  echo "not implemented for FAKEROOT=${FAKEROOT:-/}}"
  exit
fi
       
 
            
 
        
        
 
    #else
    #   echo "Unable to mount aufs br:$SANDBOX_IMG=rw$robranches"
    #   umount -l $SANDBOX_IMG  
    #fi
#else
#   echo "unable to mount rw image: $rwbranch"
#fi
 
 

Comments