diff options
Diffstat (limited to 'recipes-core/multitech/overlayfs-init-jffs2')
-rw-r--r-- | recipes-core/multitech/overlayfs-init-jffs2/config | 285 | ||||
-rwxr-xr-x | recipes-core/multitech/overlayfs-init-jffs2/overlayfs | 157 | ||||
-rw-r--r-- | recipes-core/multitech/overlayfs-init-jffs2/overlayfs.init | 145 |
3 files changed, 587 insertions, 0 deletions
diff --git a/recipes-core/multitech/overlayfs-init-jffs2/config b/recipes-core/multitech/overlayfs-init-jffs2/config new file mode 100644 index 0000000..785f99f --- /dev/null +++ b/recipes-core/multitech/overlayfs-init-jffs2/config @@ -0,0 +1,285 @@ +#!/bin/sh + +CONFIG_DIR=/var/config +RUN_CONF_DIR=/run/config + +CONFIG_PARTITION="Config" +OEM_PARTITION="OEM Config" +TABLE=$'\n'"$(cat /proc/mtd)" +if [[ $TABLE =~ [[:space:]]mtd([[:digit:]]+)[^\"]*\"$CONFIG_PARTITION\" ]] ; then + CONFIG_MTDC=/dev/mtd${BASH_REMATCH[1]} + CONFIG_MTDB=/dev/mtdblock${BASH_REMATCH[1]} +else + echo "Cannot find a ${CONFIG_PARTITION} partition" + exit 0 +fi +if [[ $TABLE =~ [[:space:]]mtd([[:digit:]]+)[^\"]*\"$OEM_PARTITION\" ]] ; then + OEM_MTDC=/dev/mtd${BASH_REMATCH[1]} + OEM_MTDB=/dev/mtdblock${BASH_REMATCH[1]} +else + echo "Cannot find a ${OEM_PARTITION} partition" + exit 0 +fi + +CONFIG_DIR=/var/config +OEM_DIR=/var/oem + +FILES="network/interfaces \ +ppp/options \ +ppp/pap-secrets \ +ppp/chap-secrets \ +ppp/peers \ +" + +# Files used by bluetooth or wifi. +BTWIFIFILES="\ +bluetooth/ \ +default/ \ +dnsmasq.d/ \ +hosts \ +hostname \ +hostapd.conf \ +modprobe.d/ \ +wpa_supplicant.conf \ +" + +# mts-io driver may not be loaded +if [[ -L /etc/default/rs9113 ]] || [[ -f /etc/default/rs9113 ]] || [[ -d /opt/rs9113 ]] ; then + BTWIFIFILES+="default/rs9113 " +fi + +# File hidden so it is not removed on hardware reset +WIFITAR=".defaults2.tar.gz" + +mount_config() { + echo "Mounting ${CONFIG_DIR}" + mkdir -p ${CONFIG_DIR} + mount ${CONFIG_DIR} + + # Prepare flash for JFFS2 or EXT4 if mount fails + if [ $? -ne 0 ]; then + echo "Creating ${CONFIG_DIR}" + fs=$(mount -fvn ${CONFIG_DIR}) + if [[ $fs =~ [[:space:]]*(/dev/(...)[^[:space:]]*) ]] ; then + if [[ ${BASH_REMATCH[2]} == mmc ]] ; then + # One more check for empty + mdev="${BASH_REMATCH[1]}" + if [[ $(dd if=$mdev count=4 2>/dev/null | tr -d '\0' | wc -c) == 0 ]] ; then + mkfs.ext4 -O 64bit ${mdev} + fi + else + flash_erase -j ${CONFIG_MTDC} 0 0 + fi + fi + mount ${CONFIG_DIR} + fi +} + +mount_oem() { + echo "Mounting ${OEM_DIR}" + mkdir -p ${OEM_DIR} + mount ${OEM_DIR} + + # Prepare flash for JFFS2 or EXT4 if mount fails + # Prepare flash for JFFS2 or EXT4 if mount fails + if [ $? -ne 0 ]; then + echo "Creating ${OEM_DIR}" + fs=$(mount -fvn ${OEM_DIR}) + if [[ $fs =~ [[:space:]]*(/dev/(...)[^[:space:]]*) ]] ; then + if [[ ${BASH_REMATCH[2]} == mmc ]] ; then + mdev="${BASH_REMATCH[1]}" + if [[ $(dd if=$mdev count=4 2>/dev/null | tr -d '\0' | wc -c) == 0 ]] ; then + mkfs.ext4 -O 64bit ${mdev} + fi + else + flash_erase -j ${OEM_MTDC} 0 0 + fi + fi + mount ${OEM_DIR} + fi +} + +# Create symlinks in directory $2 +# that point to non-directory items +# in directory $1 +# No recursion. +# +# /etc/default/rcS must be in the +# root file system +# +function linkdir { + from="$1" + to="$2" + newdir=$(basename "$from") + savedir=$(pwd) + cd "${from}" + for f in * ; do + if [[ ${to} == /etc/default ]] && [[ $f == rcS ]] ; then + continue + fi + if [[ $f == \* ]] ; then + break + fi + if ! [[ -d "${to}/${f}" ]] ; then + if ! [[ -f ${from}/${f} ]] ; then + ln -sf "${from}/${f}" "${to}/${f}" + fi + else + echo Skipping directory "$to/$f" + fi + done + cd "$savedir" +} + +# parameter 1 Input directory +# parameter 2 Parent of output directory +# +# The basename (final component) of parameter 1 +# is created as a directory in the directory +# of parameter 2. +function copydir { + from="$1" + to="$2" + newdir=$(basename "$from") + if rmdir $from >/dev/null 2>&1 ; then + ln -sf "$to/$newdir" "$from" + else + mkdir "$to/$newdir" >/dev/null 2>&1 || true + savedir=$(pwd) + cd "$from" + for f in * ; do + if [[ $f == \* ]] ; then + break + fi + if ! [[ -f "$to/$f" ]] ; then + cannon=$(readlink "$to/${newdir}/${f}" 2>/dev/null) + # Don't overwrite files in destination. + if ! [[ -f ${cannon} ]] ; then + cp -a "${f}" "$to/${newdir}/${f}" + fi + fi + done + cd "$savedir" + fi +} + +case $1 in + start) + # mount config if not already mounted + if ! grep -q " ${CONFIG_DIR} " /proc/mounts; then + mount_config + else + echo "$CONFIG_DIR already mounted" + fi + + # mount oem if specified in /etc/fstab and it isn't already mounted + if mount -fvn "${OEM_DIR}" ; then + if ! grep -q " ${OEM_DIR} " /proc/mounts; then + mount_oem + else + echo "$OEM_DIR already mounted" + fi + fi + + # Default all config files if requested + cd ${CONFIG_DIR} + if [ -f force_defaults ]; then + echo "Extracting default config files" + tar -xf /etc/defaults.tar.gz + if [[ -f ${WIFITAR} ]] ; then + echo "Extract original wifi related files" + tar -xvf ${WIFITAR} + fi + rm -f force_defaults + fi + + # Extract any missing files + TARFILES=$(tar -tf /etc/defaults.tar.gz) + for file in $TARFILES; do + if [ ! -e $file ]; then + tar -xvf /etc/defaults.tar.gz $file + fi + done + + # Create links in /etc + for file in $FILES; do + if ! [[ -L /etc/$file ]] && ! [[ -d /etc/$file ]] ; then + rm -rf /etc/$file + ln -sf ${CONFIG_DIR}/$file /etc/$file + elif [[ -d /etc/$file ]] ; then + # JAK create links in directory. + linkdir "${CONFIG_DIR}/${file}" "/etc/${file}" + fi + done + + # Move bluetooth wifi stuff to config directory. + # We don't have factory defaults. + ((dobackup=1)) + for file in ${BTWIFIFILES}; do + if [[ -L /etc/$file ]]; then + ((dobackup=0)) + break + fi + done + if ((dobackup==1)) ; then + tar -C /etc -czf ${CONFIG_DIR}/${WIFITAR} ${BTWIFIFILES} + fi + + # For jffs2, you cannot remove a populated directory in an overlay. + # We must copy individual files and create symlinks instead. + for file in ${BTWIFIFILES}; do + isdir=0 + # If last character is /, make the CONFIG directory. + if [[ ${file: -1} == / ]] ; then + isdir=1 + file=${file%?} + if ! [[ -d ${CONFIG_DIR}/$file ]] ; then + rm -f ${CONFIG_DIR}/$file 2>/dev/null || true + mkdir ${CONFIG_DIR}/$file + fi + if [[ -d ${file} ]] ; then + copydir "/etc/${file}" "${CONFIG_DIR}" + fi + fi + + if ((isdir == 0)); then + dir=$(dirname $file) + if [[ $dir != '.' ]] ; then + mkdir -p "$dir" + fi + rm -rf old + mkdir old + if ! [[ -f $file ]] ; then + # Need to preserve old files which is difficult with busybox! + if [[ -d $file ]] || [[ -f $file ]] ; then + cp --parents -a $file old || true + fi + ( + cd /etc + if [[ -d $file ]] || [[ -f $file ]] ; then + cp --parents -a $file ${CONFIG_DIR} || true + fi + ) + ( + cd old + if [[ -d $file ]] || [[ -f $file ]] ; then + cp --parents -a $file .. || true + fi + ) + rm -rf old + fi + rm -rf /etc/$file + ln -sf ${CONFIG_DIR}/$file /etc/$file + else + rm -f "/etc/${file}/*" + linkdir "${CONFIG_DIR}/${file}" "/etc/${file}" + fi + done + ;; + + *) + echo "Usage: $0 {start}" + exit 2 + ;; + +esac diff --git a/recipes-core/multitech/overlayfs-init-jffs2/overlayfs b/recipes-core/multitech/overlayfs-init-jffs2/overlayfs new file mode 100755 index 0000000..1bf0a58 --- /dev/null +++ b/recipes-core/multitech/overlayfs-init-jffs2/overlayfs @@ -0,0 +1,157 @@ +#!/bin/bash +# Command to erase user data file system + +MNT_USER="/mnt/user" +OVERLAY="$MNT_USER/overlay" +WORKDIR="$MNT_USER/work" +UPPERDIR="$MNT_USER/upper" +LOWERDIR="/" +USER_ORIG="$UPPERDIR/orig" +USER_PARTITION="User data" +TABLE=$'\n'"$(cat /proc/mtd)" + + +# Erase the file system +DO_ERASE_PERSISTENT="/mnt/user/.persistent/mts_do_erase_persistent" +# Remove files not hidden +DO_CLEAR_PERSISTENT="/mnt/user/.persistent/mts_do_clear_persistent" + +pid=$$ +prefix="<3>overlayrootfs-generator[${pid}]: " +loginfo() { echo "${prefix}$@" >/dev/kmsg ; } +logpipe() { + OIFS="${IFS}" + IFS=$'\n' + while read ln ; do + echo -n "${prefix}${ln}" >/dev/kmsg + done + IFS="${OIFS}" +} + +if [[ $TABLE =~ [[:space:]]mtd([[:digit:]]+)[^\"]*\"$USER_PARTITION\" ]] ; then + USER_DEV=/dev/mtd${BASH_REMATCH[1]} +else + loginfo "Cannot find a User data partition" + exit 0 +fi + +fs="/dev /proc /sys /run /var/volatile /dev/pts /sys/kernel/debug /sys/kernel/config" + + +mnt_user() { + mkdir -p $MNT_USER + mount -t jffs2 $USER_DEV $MNT_USER +} + +my_switch_root() { + NEW_ROOT=$1 + loginfo mountinfo + mount --make-rprivate / + loginfo "my_switch_root: Mount file systems" + for f in $fs ; do + if [[ -d $NEW_ROOT/$f ]] ; then + loginfo "my_switch_root: mount -o noatime,move --bind $f $NEW_ROOT/$f" + mount -o noatime,move --bind $f $NEW_ROOT/$f + else + # loginfo "my_switch_root: Skipping $NEW_ROOT/$f" + : + fi + done + /sbin/pivot_root $NEW_ROOT $NEW_ROOT/orig +} + +do_remove_old() { + shopt -s dotglob + rm -rf $MNT_USER/*.old + shopt -u dotglob +} + +# select files for deletion +do_clear_old() { + # when "clear user data" is requested - mark all non-hidden files for deletion + loginfo "Clearing user data. Persistent data will be left " + + for FILE_PATH in "$MNT_USER"/*; do + FILE_NAME=$(basename "$FILE_PATH") + # rename all files and folders that exist in /mnt/user + mv "$FILE_PATH" "$MNT_USER/$FILE_NAME.old" 2>&1 | logpipe + done + do_remove_old + rm -f $DO_CLEAR_PERSISTENT +} + +# Most efficient way to clear UBIFS file system +do_erase_old() { + loginfo "Erasing user data" + # Sys must be mounted to use ubifs utilities + mount -t sysfs sysfs /sys + + umount -l $MNT_USER + loginfo "Erase user-data partition $USER_DEV" + ls -l ${USER_DEV} 2>&1 | logpipe + flash_erase -j ${USER_DEV} 0 0 2>&1 | logpipe + mnt_user +} + +do_rw_mount() { + loginfo "Starting RW overlayfs" + mount -t tmpfs inittemp /mnt + + mnt_user # user_data is now accessible + do_remove_old + cat /proc/mounts | logpipe + loginfo "ls -lad /mnt" + ls -lad /mnt 2>&1 | logpipe + loginfo "ls -lad /mnt/user" + ls -lad /mnt/user 2>&1 | logpipe + loginfo "ls -lad /mnt/user/.persistent" + ls -lad /mnt/user/.persistent 2>&1 | logpipe + loginfo "ls -la /mnt/user/.persistent" + ls -la /mnt/user/.persistent 2>&1 | logpipe + loginfo "ls -lad $DO_ERASE_PERSISTENT" + ls -lad "$DO_ERASE_PERSISTENT" 2>&1 | logpipe + + if [[ -f $DO_ERASE_PERSISTENT ]] ; then + loginfo "do_erase_old is next" + do_erase_old + elif [[ -f $DO_CLEAR_PERSISTENT ]] ; then + do_clear_old + fi + + mkdir -p $UPPERDIR $WORKDIR $OVERLAY $USER_ORIG ${MNT_USER}/.persistent + loginfo "Mounting..." + mount -o index=off,metacopy=off,noatime,lowerdir=$LOWERDIR,upperdir=$UPPERDIR,workdir=$WORKDIR,rw -t overlay overlay $OVERLAY + loginfo "/proc/mounts:" + cat /proc/mounts | grep overlay | logpipe + + mkdir -p ${OVERLAY}/var/persistent + + mount --bind ${MNT_USER}/.persistent ${OVERLAY}/var/persistent + loginfo "Switch root to $OVERLAY" + my_switch_root $OVERLAY + cat /proc/mounts | grep overlay | logpipe + mount -o remount,rw / + cat /proc/mounts | grep overlay | logpipe + cat /proc/mounts | grep tmp | logpipe + umount -l /tmp >/dev/null 2>&1 + umount -l /var/volatile >/dev/null 2>&1 + cgroupmnts=$(sed -r -e 's/[^[:space:]]*[[:space:]]//' -e 's/[[:space:]]+.*//g' /proc/mounts | grep '^/orig') + for mp in ${cgroupmnts} ; do + if [[ $mp != /orig ]] && [[ -d $mp ]] ; then + umount -l $mp >/dev/null 2>&1 + fi + done +} + +do_start() { + do_rw_mount +} + +case $1 in +start) + do_start +;; +*) + echo "Usage: $0 {start}" +;; +esac diff --git a/recipes-core/multitech/overlayfs-init-jffs2/overlayfs.init b/recipes-core/multitech/overlayfs-init-jffs2/overlayfs.init new file mode 100644 index 0000000..7a4d26d --- /dev/null +++ b/recipes-core/multitech/overlayfs-init-jffs2/overlayfs.init @@ -0,0 +1,145 @@ +#!/bin/bash +# Command to erase user data file system + +MNT_USER="/mnt/user" +OVERLAY="$MNT_USER/overlay" +WORKDIR="$MNT_USER/work" +UPPERDIR="$MNT_USER/upper" +LOWERDIR="/" +USER_ORIG="$UPPERDIR/orig" +USER_PARTITION="User data" +TABLE=$'\n'"$(cat /proc/mtd)" + + +# Erase the file system +DO_ERASE_PERSISTENT="/mnt/user/.persistent/mts_do_erase_persistent" +# Remove files not hidden +DO_CLEAR_PERSISTENT="/mnt/user/.persistent/mts_do_clear_persistent" + +pid=$$ +prefix="<3>overlayrootfs-generator[${pid}]: " +loginfo() { echo "${prefix}$@" >/dev/kmsg ; } +logpipe() { + OIFS="${IFS}" + IFS=$'\n' + while read ln ; do + echo -n "${prefix}${ln}" >/dev/kmsg + done + IFS="${OIFS}" +} + +if [[ $TABLE =~ [[:space:]]mtd([[:digit:]]+)[^\"]*\"$USER_PARTITION\" ]] ; then + USER_BDEV=/dev/mtdblock${BASH_REMATCH[1]} + USER_DEV=/dev/mtd${BASH_REMATCH[1]} +else + loginfo "Cannot find a User data partition" + exit 0 +fi + +fs="/dev /proc /sys /run /var/volatile /dev/pts /sys/kernel/debug /sys/kernel/config" + + +mnt_user() { + mkdir -p $MNT_USER + mount -t jffs2 $USER_BDEV $MNT_USER +} + +my_switch_root() { + NEW_ROOT=$1 + loginfo mountinfo + mount --make-rprivate / + loginfo "my_switch_root: Mount file systems" + for f in $fs ; do + if [[ -d $NEW_ROOT/$f ]] ; then + loginfo "my_switch_root: mount -o noatime,move --bind $f $NEW_ROOT/$f" + mount -o noatime,move --bind $f $NEW_ROOT/$f + else + # loginfo "my_switch_root: Skipping $NEW_ROOT/$f" + : + fi + done + /sbin/pivot_root $NEW_ROOT $NEW_ROOT/orig +} + +do_remove_old() { + shopt -s dotglob + rm -rf $MNT_USER/*.old + shopt -u dotglob +} + +# select files for deletion +do_clear_old() { + # when "clear user data" is requested - mark all non-hidden files for deletion + loginfo "Clearing user data. Persistent data will be left " + + for FILE_PATH in "$MNT_USER"/*; do + FILE_NAME=$(basename "$FILE_PATH") + # rename all files and folders that exist in /mnt/user + mv "$FILE_PATH" "$MNT_USER/$FILE_NAME.old" 2>&1 | logpipe + done + do_remove_old + rm -f $DO_CLEAR_PERSISTENT +} + +# Most efficient way to clear UBIFS file system +do_erase_old() { + loginfo "Erasing user data" + # Sys must be mounted to use ubifs utilities + mount -t sysfs sysfs /sys + + umount -l $MNT_USER + loginfo "Erase user-data partition $USER_DEV" + flash_erase -j ${USER_DEV} 0 0 2>&1 | logpipe + mnt_user +} + +do_rw_mount() { + loginfo "Starting RW overlayfs" + mount -t tmpfs inittemp /mnt + + mnt_user # user_data is now accessible + do_remove_old + + if [[ -f $DO_ERASE_PERSISTENT ]] ; then + do_erase_old + elif [[ -f $DO_CLEAR_PERSISTENT ]] ; then + do_clear_old + fi + + mkdir -p $UPPERDIR $WORKDIR $OVERLAY $USER_ORIG ${MNT_USER}/.persistent + loginfo "Mounting..." + mount -o index=off,metacopy=off,noatime,lowerdir=$LOWERDIR,upperdir=$UPPERDIR,workdir=$WORKDIR,rw -t overlay overlay $OVERLAY + loginfo "/proc/mounts:" + cat /proc/mounts | grep overlay | logpipe + + mkdir -p ${OVERLAY}/var/persistent + + mount --bind ${MNT_USER}/.persistent ${OVERLAY}/var/persistent + loginfo "Switch root to $OVERLAY" + my_switch_root $OVERLAY + cat /proc/mounts | grep overlay | logpipe + mount -o remount,rw / + cat /proc/mounts | grep overlay | logpipe + cat /proc/mounts | grep tmp | logpipe + umount -l /tmp >/dev/null 2>&1 + umount -l /var/volatile >/dev/null 2>&1 + cgroupmnts=$(sed -r -e 's/[^[:space:]]*[[:space:]]//' -e 's/[[:space:]]+.*//g' /proc/mounts | grep '^/orig') + for mp in ${cgroupmnts} ; do + if [[ $mp != /orig ]] && [[ -d $mp ]] ; then + umount -l $mp >/dev/null 2>&1 + fi + done +} + +do_start() { + do_rw_mount +} + +case $1 in +start) + do_start +;; +*) + echo "Usage: $0 {start}" +;; +esac |