#!/bin/bash
##
## Generic script to overlay (aufs) a persistent rootfs with a tmpfs,
## so that writes go only to RAM rather than the real root device.
## We use tmpfs, rather than ramfs, so that total usage can be limited,
## to half of RAM by default.
##
## The real rootfs is still accessible as /.rw/ when needed.
## If any step fails, we abort and continue with normal system init.
##
## Invoke with "init=/ram/init" on the kernel command line.
## 
echo "$0: Preparing system to run from RAM"

PATH="$PATH:/sbin:/usr/sbin"
INIT=/sbin/init
OLDROOT=.rw	## where the persistent real-root ends up
TMPFS=.tmpfs	## where the tmpfs gets mounted
NEWROOT=.aufs	## where the aufs gets mounted
ROOTOPTS="noatime"
RAM=/ram	## holds replacments for system files
cd /

## Create mount points (if not already there) for the tmpfs and aufs filesystems:
if [ ! -d "${TMPFS}" -o ! -d "${NEWROOT}" ]; then
	mount -n / -oremount,rw,relatime,errors=remount-ro
	mkdir -p "${TMPFS}" "${NEWROOT}"  || exec "${INIT}"
	chmod 0755 "${TMPFS}" "${NEWROOT}"
	mount -n / -oremount,ro
fi

## Mount the tmpfs RAM-based filesystem:
mount -n tmpfs "${TMPFS}" -t tmpfs -o "size=70%" || exec "${INIT}"
chmod 0755 "${TMPFS}"	## Fix permissions; mount fails to pass along the mode option

## Use aufs to overlay the tmpfs on top of the rootfs:
mount -n -t aufs -o"$ROOTOPTS,br:${TMPFS}=rw:/=ro" none ${NEWROOT} || exec "${INIT}"
chmod 0755 "${NEWROOT}"	## Fix permissions

## Now pivot over to the new aufs root filesystem:
mkdir -p --mode=0755 "${NEWROOT}/${OLDROOT}" || exec "${INIT}"
cd "${NEWROOT}" || exec "${INIT}"
pivot_root . "${OLDROOT}"
cd /

## Remove phantom mount points from the aufs:
rmdir "${NEWROOT}" "${TMPFS}"

## Ensure we have the necessary mount points for various pseudo filesystems:
mkdir -p --mode=0755 /dev /proc /sys

## Move /dev (udev) directory to new root, if it was already mounted:
mount -n -t proc  none /proc
awk "(\$2 == \"/${OLDROOT}/dev\"){exit 1}" < /proc/mounts || mount -n --move /${OLDROOT}/dev /dev
umount -n /proc

## Move proc and sysfs to new root, if they were already mounted:
[ -d /${OLDROOT}/proc/1     ] && mount -n --move /${OLDROOT}/proc /proc
[ -d /${OLDROOT}/sys/kernel ] && mount -n --move /${OLDROOT}/sys  /sys

## Overlay /tmp with a tmpfs:
mkdir -p --mode=1777 /tmp
mount -n -t tmpfs none /tmp
chmod 01777 /tmp

if [ 1 -eq 1 ]; then
if [ -d /var/log ]; then
	## Overlay /var/log with a tmpfs, and pre-populate with sub-directories:
	mount -n -t tmpfs none /var/log
	chmod 0755 /var/log
	cd ${OLDROOT}
	find var/log -type d -exec mkdir -p "/{}"               \;
	find var/log -type d -exec chmod --reference="{}" "/{}" \;
	find var/log -type d -exec chown --reference="{}" "/{}" \;
	cd /
fi
fi

## Create a default /etc/mtab file on the new aufs:
echo "none / aufs rw,$ROOTOPTS 0 0" > "/etc/mtab"

/ram/rearrange_sysfiles_for_ram_session install "$RAM"

## Launch the distro's /sbin/init stuff:
[ -x "${INIT}.real" ] && INIT="${INIT}.real"
echo "$0: Done, launching ${INIT}"
exec chroot . "${INIT}" < /dev/console > /dev/console 2>&1
"${INIT}" < /dev/console > /dev/console 2>&1
