Advertisement
s243a

sandbox2.sh

Jan 18th, 2020
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 11.23 KB | None | 0 0
  1. #!/bin/bash
  2. # James Budiono 2011, 2013, 2015
  3. # puppy test/compilation sandbox
  4. # this version uses tmpfs instead of an rw image,
  5. # and you can also choose which SFS to use
  6. # run this from terminal.
  7. # version 4 - replace sed with awk - more powerful and more correct, will handle all oddball cases
  8. #             where loop-N and pup_ro-N numbers don't match
  9. # version 5 - add compatibility when running with pup_rw=tmpfs (step 2.a)
  10. # version 6 - (2012) adapted to be more flexible - for Fatdog64 600
  11. # version 7 - (2012) cleanup mounts if if we are killed
  12. # version 8 - (2013) re-launch in terminal if we aren't in terminal
  13. # version 9 - (2013) enable running multiple sandboxes
  14. # version 10 - (2015) use pid/mount namespaces if available
  15.  
  16. # 0. directory locations
  17. #. $BOOTSTATE_PATH # AUFS_ROOT_ID
  18. #XTERM="defaultterm"
  19. # -o, --output-file
  20. #    Just write layer paths to an output file but don't mount the sandbox.
  21. # --no-exit
  22. #   if an output file is specified (i.e. -o or --output-file) layer paths are just written to a file and the program exits unless the no-exit flag is specified.
  23. # f, --input-file
  24. #   read layer paths from a file rather than reading existing layers
  25. # m,--pmedia
  26. #   determines pupmodes. Refer to puppy boot parmaters
  27. # d, --pdrv
  28. #   this is the particiaion where the puppy files are located. The default is /mnt/home
  29. # s, psubdir
  30. #   this is the sub directory where the puppy files are located
  31. # c, --clear-env
  32. #   deletes enviornental variabls
  33. # --env-prefix
  34. #   enviornental variable prefix
  35. # b --boot-config
  36. #   path to boot config (e.g. /etc/rc.d/BOOTCONFIG
  37. # --disto-specs
  38. #   path to distro specs (e.g. /etc/DISTRO_SPECS; e.g. /initrd/distro-specs)
  39. # L, --layer
  40. #   a subgke kater
  41. #  e, --extra-sfs
  42. #   a list of extra sfs files (space seperated)
  43. #  u, --union-record
  44. # --xterm
  45. # --sandbox
  46. # -initrd
  47.  
  48. XTERM=${XTERM:-urxvt}
  49. SANDBOX_ROOT=${SANDBOX_ROOT:-/mnt/sb}
  50. declare -a options="$(getopt -o f:,o:,m:,d:,s:,b:,e: --long input-file:output-file:,pmedia:,pdrv:,psubdir:,boot-config:,--distro-specs,--extra-sfs -- "$@")"
  51. declare -a options2
  52. declare -a LAYER_SOURCES
  53. LAYER_SOURCE=none
  54. eval set --"$options"
  55. while [ $# -gt 0 ]; do
  56.   case "$1" in
  57.   -f|--input-file) INPUT_FILE=$2;
  58.     LAYER_SOURCE=INPUT_FILE
  59.     LAYER_SOURCES+=( input-file )
  60.     shift 2; ;;      
  61.   -o|--output-file) OUTPUT_FILE=$2; shift 2; ;;
  62.   --no-exit)
  63.     if [ $# -gt 1 ] && [[ ! "$2" = --* ]]; then
  64.       NO_EXIT="$2"
  65.     else
  66.       NO_EXIT=true
  67.     fi; ;;
  68.   -p|--env-prefix) ENV_PREFIX=$2; shift 2; ;;
  69.   -m|--pmedia) PMEDIA=$2; shift 2; ;;
  70.   -d| --pdrv) PDRV=$2; shift 2; ;;
  71.   -s|--psubdir) PSUBDIR=$2;
  72.     LAYER_SOURCE=psubdir  
  73.     LAYER_SOURCES+=( psubdir )
  74.     shift 2; ;;
  75.   --distro-specs)
  76.      DISTRO_SPECS=$2;
  77.      . "$DISTRO_SPECS"
  78.      shift 2
  79.      ;;
  80.    --boot-config)
  81.        DISTRO_SPECS=$2;
  82.      . "$BOOTCONFIG"
  83.      shift 2
  84.      ;;
  85.    --union-record)  
  86.      LASTUNIONRECORD="$2";
  87.      LAYER_SOURCES+=( union-record )
  88.      shift 2; ;;
  89.    -e|--extra-sfs)
  90.      EXTRASFSLIST="$2";
  91.      LAYER_SOURCES+=( extrasfs )
  92.      shift 2; ;;
  93.   --)
  94.     shift 1
  95.     options2+=( "$@" )
  96.     break; ;;
  97.   *)
  98.      options2+=( "$1" )
  99.      shift 1; ;;
  100.   esac
  101. done
  102.  
  103. #set -- "${options2[@]}"
  104. if [ "$LAYER_SOURCE" = none ] && [ ! -z "$PDRV" ]; then
  105.   PDRV=${PDRV:-/mnt/home}
  106.   for rec in $LASTUNIONRECORD; do
  107.     if [ -f "$pdrv/$rec" ]; then
  108.       items+="$pdrv/$rec" "$rec"$'\n'
  109.     fi
  110.   done
  111.   if [ -z "$items" ]; then
  112.     [ -z "$DISTRO_PUPPYSFS" ] && DISTRO_PUPPYSFS=$(ls -1 /mnt/home | grep -m1 puppy_.*\.sfs$)
  113.     [ -z "$DISTRO_ZDRVSFS" ] && DISTRO_ZDRVSFS=$(ls -1 /mnt/home | grep -m1 zdrv.*\.sfs$)
  114.     [ -z "$DISTRO_FDRVSFS" ] && DISTRO_FDRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)
  115.     [ -z "$DISTRO_ADRVSFS" ] && DISTRO_ADRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)    
  116.     [ -z "$DISTRO_YDRVSFS" ] && DISTRO_YDRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)    
  117.     for rec in "$DISTRO_PUPPYSFS" "$DISTRO_ZDRVSFS" "$DISTRO_FDRVSFS" "$DISTRO_ADRVSFS" "$DISTRO_YDRVSFS"; do
  118.       items+="$pdrv/$rec" "$rec"$'\n'  
  119.     done
  120.   fi
  121.   if [ ! -z "$items" ]; then  
  122.     for rec in $EXTRASFSLIST; do
  123.       if [ -f "$pdrv/$rec" ]; then
  124.         items+="$pdrv/$rec" "$rec"$'\n'
  125.       fi
  126.     done
  127.   fi
  128. fi
  129. if [ -z "$items" ]; then
  130.     LAYER_SOURCE=aufs  
  131.     LAYER_SOURCES+=( aufs )
  132. fi
  133. FAKEROOT=$SANDBOX_ROOT/fakeroot   # mounted chroot location of sandbox - ie, the fake root
  134. SANDBOX_TMPFS=$SANDBOX_ROOT/sandbox # mounted rw location of tmpfs used for sandbox
  135. SANDBOX_ID=
  136. TMPFILE=$(mktemp -p /tmp)
  137. # use namespaces if available
  138. #[ -e /proc/1/ns/pid ] && [ -e /proc/1/ns/mnt ] && type unshare >/dev/null && USE_NS=1
  139.  
  140.  
  141.  
  142.  
  143. # umount all if we are accidentally killed
  144. trap 'umountall' 1
  145. umountall() {
  146.     {
  147.     umount -l $FAKEROOT/$SANDBOX_TMPFS
  148.     umount -l $FAKEROOT/tmp
  149.     umount -l $FAKEROOT/proc
  150.     umount -l $FAKEROOT/sys
  151.     umount -l $FAKEROOT/dev
  152.    
  153.     umount -l $FAKEROOT
  154.     umount -l $SANDBOX_TMPFS
  155.     rmdir $FAKEROOT
  156.     rmdir $SANDBOX_TMPFS
  157.     } 2> /dev/null
  158. }
  159.  
  160. # 0.1 must be root
  161. if [ $(id -u) -ne 0 ]; then
  162.     echo "You must be root to use sandbox."
  163.     exit
  164. fi
  165.  
  166. # 0.2 cannot launch sandbox within sandbox
  167. if [ "$AUFS_ROOT_ID" != "" ] ; then
  168.     grep -q $SANDBOX_ROOT /sys/fs/aufs/$AUFS_ROOT_ID/br0 &&
  169.         echo "Cannot launch sandbox within sandbox." && exit
  170. fi
  171.  
  172. # 0.3 help
  173. case "$1" in
  174.     --help|-h)
  175.     echo "Usage: ${0##*/}"
  176.     echo "Starts an in-memory (throwaway) sandbox. Type 'exit' to leave."
  177.     exit
  178. esac
  179.  
  180. # 0.4 if not running from terminal but in Xorg, then launch via terminal
  181. ! [ -t 0 ] && [ -n "$DISPLAY" ] && exec $XTERM -e "$0" "$@"
  182. ! [ -t 0 ] && exit
  183. # 1. get aufs system-id for the root filesystem
  184. if [ -z "$AUFS_ROOT_ID" ] ; then
  185.     AUFS_ROOT_ID=$(
  186.         awk '{ if ($2 == "/" && $3 == "aufs") { match($4,/si=[0-9a-f]*/); print "si_" substr($4,RSTART+3,RLENGTH-3) } }' /proc/mounts
  187.     )
  188. fi
  189. if [ -z "$items" ]; then
  190.  
  191.   for item_source in "${LAYER_SOURCES[@]}"; do
  192.   # 2. get branches, then map branches to mount types or loop devices
  193.     case "$item_source" in
  194.     input-file)
  195.   items+=$(cat "$INPUT_FILE")$'\n'; ;;
  196.     union-record)
  197.        for rec in $LASTUNIONRECORD; do
  198.         if [ -f "$rec" ]; then
  199.           items+="$rec" "$(basename "$rec")"$'\n'
  200.         elif [ -f "$pdrv/$rec" ]; then
  201.           items+="$pdrv/$rec" "$rec, "'"on"'$'\n'
  202.         fi
  203.       done
  204.       ;;
  205.     extra-sfs)
  206.        for rec in $EXTRASFSLIST; do
  207.        if [ -f "$rec" ]; then
  208.           items+="$rec" "$(basename "$rec")"$'\n'  
  209.         elif [ -f "$pdrv/$rec" ]; then
  210.           items+="'$pdrv/$rec', '$rec', "'"on"'$'\n'
  211.         fi
  212.       done
  213.       ;;
  214.     layer=*)
  215.       item_path="$(echo ${litem_source#*=})"
  216.       items+="'$item_path', '$(basename "$item_path")', "'"on"'$'\n'
  217.       ;;
  218.     psubdir)
  219.       [ -z "$DISTRO_PUPPYSFS" ] && DISTRO_PUPPYSFS=$(ls -1 /mnt/home | grep -m1 puppy_.*\.sfs$)
  220.       [ -z "$DISTRO_ZDRVSFS" ] && DISTRO_ZDRVSFS=$(ls -1 /mnt/home | grep -m1 zdrv.*\.sfs$)
  221.       [ -z "$DISTRO_FDRVSFS" ] && DISTRO_FDRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)
  222.       [ -z "$DISTRO_ADRVSFS" ] && DISTRO_ADRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)    
  223.       [ -z "$DISTRO_YDRVSFS" ] && DISTRO_YDRVSFS=$(ls -1 /mnt/home | grep -m1 fdrv.*\.sfs$)    
  224.       for rec in "$DISTRO_PUPPYSFS" "$DISTRO_ZDRVSFS" "$DISTRO_FDRVSFS" "$DISTRO_ADRVSFS" "$DISTRO_YDRVSFS"; do
  225.         items+="'$pdrv/$rec', '$rec', "'"on"'$'\n'  
  226.       done
  227.       ;;      
  228.     aufs)
  229.   items+=$(
  230.   { echo ==mount==; cat /proc/mounts;
  231.     echo ==losetup==; losetup-FULL -a;
  232.     echo ==branches==; ls -v /sys/fs/aufs/$AUFS_ROOT_ID/br[0-9]* | xargs sed 's/=.*//'; } | \
  233.     awk '
  234.    /==mount==/ { mode=1 }
  235.    /==losetup==/ { mode=2 }
  236.    /==branches==/ { mode=3 }
  237.    {
  238.    if (mode == 1) {
  239.      # get list of mount points, types, and devices - index is $3 (mount points)
  240.      mountdev[$2]=$1
  241.      mounttypes[$2]=$3
  242.    } else if (mode == 2) {
  243.      # get list of loop devices and files - index is $1 (loop devs)
  244.      sub(/:/,"",$1)
  245.      sub(/.*\//,"",$3); sub(/)/,"",$3)
  246.      loopdev[$1]=$3
  247.    } else if (mode == 3) {
  248.      # map mount types to loop files if mount devices is a loop
  249.      for (m in mountdev) {
  250.        if ( loopdev[mountdev[m]] != "" ) mounttypes[m]=loopdev[mountdev[m]]
  251.      }
  252.      # for (m in mountdev) print m " on " mountdev[m] " type " mounttypes[m]
  253.      mode=4
  254.    } else if (mode==4) {
  255.      # print the branches and its mappings
  256.      if ($0 in mounttypes){
  257.        print $0, mounttypes[$0], "on"
  258.      }
  259.      else {
  260.        MNT_PATH=$0
  261.        sub(/^.*[\/]/,"")
  262.        print MNT_PATH, $0, "on"
  263.      }
  264.    }
  265.    }  
  266.  '
  267.   )$'\n'
  268.   # '
  269.   ;;
  270.   esac
  271.   done
  272. fi
  273. # 3. Ask user to choose the SFS
  274. dialog --separate-output --backtitle "tmpfs sandbox" --title "sandbox config" \
  275.     --checklist "Choose which SFS you want to use" 0 0 0 $items 2> $TMPFILE
  276. chosen="$(cat $TMPFILE)"
  277.  
  278. clear
  279. if [ -z "$chosen" ]; then
  280.     echo "Cancelled or no SFS is chosen - exiting."
  281.     exit 1
  282. fi
  283.  
  284. if [ ! -z "$OUTPUT_FILE" ]; then
  285.   cp "$TMPFILE" "$OUTPUT_FILE"
  286.   if [ ! "$NO_EXIT" = true ]; then
  287.     exit 0
  288.   fi
  289. fi
  290. # 0.5 is this the first sandbox? If not, then create another name for mountpoints
  291. if grep -q $FAKEROOT /proc/mounts; then
  292.     FAKEROOT=$(mktemp -d -p $SANDBOX_ROOT ${FAKEROOT##*/}.XXXXXXX)
  293.     SANDBOX_ID=".${FAKEROOT##*.}"
  294.     SANDBOX_TMPFS=$SANDBOX_ROOT/${SANDBOX_TMPFS##*/}${SANDBOX_ID}
  295.     rmdir $FAKEROOT
  296. fi
  297.  
  298.  
  299.  
  300. # 4. convert chosen SFS to robranches
  301. robranches=""
  302. for a in $(cat $TMPFILE) ; do
  303.     robranches=$robranches:$a=ro
  304. done
  305. rm $TMPFILE
  306.  
  307. # 5. make the mountpoints if not exist  yet
  308. mkdir -p $FAKEROOT $SANDBOX_TMPFS
  309.  
  310. # 6. do the magic - mount the tmpfs first, and then the rest with aufs
  311. if mount -t tmpfs none $SANDBOX_TMPFS; then
  312.     if mount -t aufs -o "br:$SANDBOX_TMPFS=rw$robranches" aufs $FAKEROOT; then
  313.         # 5. record our new aufs-root-id so tools don't hack real filesystem   
  314.         SANDBOX_AUFS_ID=$(grep $FAKEROOT /proc/mounts | sed 's/.*si=/si_/; s/ .*//') #'
  315.         sed -i -e '/AUFS_ROOT_ID/ d' $FAKEROOT/etc/BOOTSTATE 2> /dev/null
  316.         echo AUFS_ROOT_ID=$SANDBOX_AUFS_ID >> $FAKEROOT/etc/BOOTSTATE
  317.        
  318.         # 7. sandbox is ready, now just need to mount other supports - pts, proc, sysfs, usb and tmp
  319.         mkdir -p $FAKEROOT/dev $FAKEROOT/sys $FAKEROOT/proc $FAKEROOT/tmp
  320.         mount -o rbind /dev $FAKEROOT/dev
  321.         mount -t sysfs none $FAKEROOT/sys
  322.         mount -t proc none $FAKEROOT/proc
  323.         mount -o bind /tmp $FAKEROOT/tmp
  324.         mkdir -p $FAKEROOT/$SANDBOX_TMPFS
  325.         mount -o bind $SANDBOX_TMPFS $FAKEROOT/$SANDBOX_TMPFS   # so we can access it within sandbox
  326.        
  327.         # 8. optional copy, to enable running sandbox-ed xwin
  328.         cp /usr/share/sandbox/* $FAKEROOT/usr/bin 2> /dev/null
  329.        
  330.         # 9. make sure we identify ourself as in sandbox - and we're good to go!
  331.         echo -e '\nexport PS1="sandbox'${SANDBOX_ID}'# "' >> $FAKEROOT/etc/shinit #fatdog 600
  332.         sed -i -e '/^PS1/ s/^.*$/PS1="sandbox'${SANDBOX_ID}'# "/' $FAKEROOT/etc/profile # earlier fatdog
  333.         echo "Starting sandbox now."
  334.         if [ $USE_NS ]; then
  335.             unshare -f -p --mount-proc=$FAKEROOT/proc chroot $FAKEROOT
  336.         else
  337.             chroot $FAKEROOT
  338.         fi
  339.  
  340.         # 10. done - clean up everything
  341.         umountall
  342.         echo "Leaving sandbox."
  343.     else
  344.         echo "Unable to mount aufs br:$SANDBOX_TMPFS=rw$robranches"
  345.         umount -l $SANDBOX_TMPFS       
  346.     fi
  347. else
  348.     echo "unable to mount tmpfs."
  349. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement