how the sandbox.sh script works
Someone recently asked if you can load a different save file after boot (see thread), and I thought that there would be useful code examples on how to do this on both sandbox.sh and psandbox. The first thing I would like to look at how the script gathers information about the various pup layers.
Each aufs file system has a unique id. The script obtains this id for the root file system as follows:
Code: Select all
AUFS_ROOT_ID=$(awk '{ if ($2 == "/" && $3 == "aufs") { match($4,/si=[0-9a-f]*/); print "si_" substr($4,RSTART+3,RLENGTH-3) } }' /proc/mounts)
/woof-code/rootfs-skeleton/usr/bin/sandbox.sh#L79
In this folder there is a file for each layer. Each file contains the mount point and the write permissions for the corresponding layer. For instance:
Code: Select all
# cat /sys/fs/aufs/$AUFS_ROOT_ID/br0
/initrd/mnt/tmpfs/pup_rw=rw
br0, is the top layer, br1 is the next layer down and so on. The sandbox.sh expects at most nine layers:
Code: Select all
echo ==branches==; ls -v /sys/fs/aufs/$AUFS_ROOT_ID/br[0-9]*
/woof-code/rootfs-skeleton/usr/bin/sandbox.sh#L88
The "==branches==" string is a flag to tell the AWK script how to process the output.The advantage of this folder (i.e. /sys/fs/aufs/$AUFS_ROOT_ID) is that it gives all the layers for a particular aufs file system and the order of each layer. Knowing how puppy works we could infer the layer order by the name of the mount path:
Code: Select all
# cat /proc/mounts | grep pup
/dev/loop0 /initrd/pup_ro2 squashfs ro,noatime 0 0
/dev/loop1 /initrd/pup_f squashfs ro,noatime 0 0
/dev/loop2 /initrd/pup_z squashfs ro,noatime 0 0
/dev/loop3 /initrd/pup_a squashfs ro,noatime 0 0
/dev/loop4 /initrd/pup_ro3 squashfs ro,noatime 0 0
but this doesn't tell us the actual name of the file mounted and it doesn't tell us about any layers that aren't mount points (e.g. a save folder). The aufs file system folder (i.e. /sys/fs/aufs/$AUFS_ROOT_ID) will tell us about layers that aren't mount points, and we can get the actual file name by matching the loop device given in /proc/mounts with the following command:
Code: Select all
# losetup-FULL -a
/dev/loop1: [0018]:3210 (/initrd/mnt/tmpfs/fdrv_upupgg+d_20.10.sfs)
/dev/loop4: [2100]:269290 (/initrd/mnt/dev_save/upup/GG/+D/20/10/devx_upupgg+d_20.10.sfs)
/dev/loop2: [0018]:2319 (/initrd/mnt/tmpfs/zdrv_upupgg+d_20.10.sfs)
/dev/loop0: [0018]:2308 (/initrd/mnt/tmpfs/puppy_upupgg+d_20.10.sfs)
/dev/loop3: [0018]:2324 (/initrd/mnt/tmpfs/adrv_upupgg+d_20.10.sfs)
The sandbox.sh script uses all this information in order to get the layer order, mount point and filename.
Code: Select all
# 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 }
https://github.com/puppylinux-woof-CE/w ... box.sh#L84
The layer order and mount point are necessary and the file name is useful to determine which layers that we want to mount in the sandbox. For example do we want to mount devx as one of the layers?
The script uses a terminal based gui (i.e. dialog) to let the user determine which layers to mount:
Code: Select all
# 3. Ask user to choose the SFS
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)"
/woof-code/rootfs-skeleton/usr/bin/sandbox.sh#L126
In the case of the sandbox, the top layer is in ram (i.e. tmpfs) and the bottom layers are read only. The bottom layers are defined with the following code:
Code: Select all
# 4. convert chosen SFS to robranches
robranches=""
for a in $(cat $TMPFILE) ; do
robranches=$robranches:$a=ro
done
/woof-code/rootfs-skeleton/usr/bin/sandbox.sh#L137
First the top layer of the sandbox is mounted at " $SANDBOX_TMPFS",
Code: Select all
mount -t tmpfs none $SANDBOX_TMPFS
/woof-code/rootfs-skeleton/usr/bin/sandbox.sh#L148
and if this succeeds then we mount all sandbox layers at "$FACKEROOT" in a new aufs file system at "$FAKEROOT"
Code: Select all
mount -t aufs -o "br:$SANDBOX_TMPFS=rw$robranches" aufs $FAKEROOT
Each aufs file system has a unique mount point. For instance the running puppy is mounted on root:
Code: Select all
# cat /proc/mounts | grep aufs
unionfs / aufs rw,relatime,si=5413df1e 0 0