diff --git a/recipes-support/backup-scripts/backup-scripts_1.0.bb b/recipes-support/backup-scripts/backup-scripts_1.0.bb new file mode 100644 index 0000000..e299fc8 --- /dev/null +++ b/recipes-support/backup-scripts/backup-scripts_1.0.bb @@ -0,0 +1,72 @@ +SUMMARY = "Backup scripts" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD;md5=3775480a712fc46a69647678acb234cb" + +SRC_URI += "file://cbackup \ +file://cbackup.sh \ +file://mbackup \ +file://mbackup.sh \ +file://checkbk \ +file://checkbk.service \ +file://checkflashcfg \ +file://checkflash.service \ +" + +S = "${WORKDIR}" + +# set this variable to 0 to avoid blocking the boot process if flash configuration is not valid +# normally keep it to 1, in upper layers except if there is no way to know that a flash repair +# is needed from external server +export BLOCKOPTION = "0" + +inherit gitver-repo + +REPODIR = "${THISDIR}" +REPOFILE = "backup-scripts_1.0.bb" +PR := "r${REPOGITFN}" + +REPODIR = "${THISDIR}/files" +REPOFILE = "" +PR := "${PR}.${REPOGITFN}" + +RDEPENDS_${PN} += "busybox cronie util-linux coreutils base-files" + +do_install() { + install -d ${D}${sysconfdir} + install -d ${D}${sysconfdir}/systemd + install -d ${D}${sysconfdir}/systemd/system + install -d ${D}${sysconfdir}/systemd/system/multi-user.target.wants + install -m 0755 -d ${D}${base_libdir} + install -m 0755 -d ${D}${systemd_unitdir} + install -m 0755 -d ${D}${systemd_unitdir}/system + install -m 0644 ${S}/checkbk.service ${D}${systemd_unitdir}/system/checkbk.service + ln -sf ${systemd_unitdir}/system/checkbk.service ${D}${sysconfdir}/systemd/system/multi-user.target.wants/checkbk.service + install -m 0644 ${S}/checkflash.service ${D}${systemd_unitdir}/system/checkflash.service + ln -sf ${systemd_unitdir}/system/checkflash.service ${D}${sysconfdir}/systemd/system/multi-user.target.wants/checkflash.service + install -d ${D}${bindir} + install -m 0755 ${S}/cbackup ${D}${bindir}/.cbackup + install -m 0755 ${S}/mbackup ${D}${bindir}/.mbackup + install -m 0755 ${S}/cbackup.sh ${D}${bindir}/cbackup + install -m 0755 ${S}/mbackup.sh ${D}${bindir}/mbackup + install -m 0755 ${S}/checkbk ${D}${bindir}/checkbk + install -m 0755 ${S}/checkflashcfg ${D}${bindir}/checkflashcfg + echo "BLOCKOPTION=${BLOCKOPTION}" > ${D}${sysconfdir}/bootoptions.conf + chmod 755 ${D}${sysconfdir}/bootoptions.conf +} + +pkg_postinst_${PN}_append() { + echo "adding crontab" + test -d $D/var/spool/cron || mkdir -p $D/var/spool/cron + test -f /var/spool/cron/root && sed -i '/checkbk/d' $D/var/spool/cron/root + echo "15 3 * * * nice -n 15 ${bindir}/checkbk" >> $D/var/spool/cron/root +} + +FILES_${PN} += "${bindir}/mbackup \ +${bindir}/.mbackup \ +${bindir}/cbackup \ +${bindir}/.cbackup \ +${bindir}/checkbk \ +${bindir}/checkflashcfg \ +${sysconfdir} \ +${systemd_unitdir}/* \ + " diff --git a/recipes-support/backup-scripts/files/cbackup b/recipes-support/backup-scripts/files/cbackup new file mode 100644 index 0000000..e8c5d27 --- /dev/null +++ b/recipes-support/backup-scripts/files/cbackup @@ -0,0 +1,190 @@ +#!/bin/sh +STAG=cbackup: +# lock wait time max 15mn * 60 = 900 secs (sufficient time to update) +LOCKWAIT=900 +# this is a protection to make sure a backup is not currently created while checking +bname=mbackup +BAKPATH="" +_curr_dir="" +BAKEXT=".tar.gz" +BAKMD5EXT=".md5" +mybasename="" + +readonly LOCKFILE_DIR=/var/lock +readonly LOCK_FD=980 + +lock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # still allow to run unlocked if the lock dir does not exist + if [ ! -d "${LOCKFILE_DIR}" ]; then + return 0 + fi + + # create lock file + eval "exec $fd>$lock_file" + # still allow to run unlocked if the lock file cannot be created + if [ $? -ne 0 ]; then + return 0 + fi + + # acquier the lock + flock -w ${LOCKWAIT} $fd \ + && return 0 \ + || return 1 +} + +unlock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # release the lock + flock -u $fd + sync +} + +function my_exit() +{ + cd "$_curr_dir" + unlock $bname + exit $* +} + +function __sig_int { + log_write " " + log_write "$STAG WARNING: SIGINT caught" + my_exit 110 +} + +function __sig_quit { + log_write " " + log_write "$STAG WARNING: SIGQUIT caught" + my_exit 111 +} + +function __sig_term { + log_write " " + log_write "$STAG WARNING: SIGTERM caught" + my_exit 112 +} + +function __sig_hup { + log_write " " + log_write "$STAG WARNING: SIGHUP caught" + my_exit 113 +} + +function log_write() +{ + echo "$*" +} + +function log_write_nr() +{ + echo -n "$*" +} + +function show_help { + log_write "cbackup help information:" + log_write "checks integrity of backup created with mbackup, exit with 0 when valid" + log_write "Usage: cbackup [ --help ] " + log_write " where: # source backup base file name (without .tar.gz)" + log_write " # same base file name as provided with mbackup -f option" + log_write " --help # displays this help information" + log_write "example: cbackup /mnt/storage/.sysbackup/bk-mnt-rom-user # checks backup" +} + +function check_path() +{ + local retval=0 + local slen=${#1} + local mystr + if ! [ -d $1 ] ; then + log_write "$STAG directory does not exist ($1)!" + retval=80 + else + if [ "${1:$slen - 1:1}" == "/" ] ; then + mystr=${1:0:$slen - 1} + slen=$((slen-1)) + else + mystr=$1 + fi + BAKPATH=$mystr"/" + fi + return $retval +} + +_curr_dir=`pwd` + +# Lock to test a single instance is running, and exit if wait timeout +log_write "$STAG Checking if allowed to run..." +lock $bname || ( log_write "$STAG Checking if allowed to run... failed"; exit 100 ) +log_write "$STAG Checking if allowed to run... done" + +# Set TRAPs to release lock if forced to exit +trap __sig_int SIGINT +trap __sig_quit SIGQUIT +trap __sig_term SIGTERM +trap __sig_hup SIGHUP + +TOTALARG=$# +while getopts :- FLAG; do + case $FLAG in + '-') + show_help + my_exit 0;; + \?) + log_write "Invalid option: -$OPTARG" && my_exit 1;; + \:) + log_write "Required argument not found for option: -$OPTARG" && my_exit 2;; + esac +done + +# removes processed option(s) from the cmd line args +shift $((OPTIND-1)) + +if [ "$#" -ne 1 ]; then + show_help + my_exit 3 +fi + +check_path `dirname "$1"` +valret=$? +if [ $valret -ne 0 ]; then + my_exit $valret +fi +mybasename=`basename "$1"` + +log_write "$STAG Checking backup: "$BAKPATH$mybasename +if ! [ -f $BAKPATH$mybasename$BAKEXT ] ; then + log_write "$STAG Source backup does not exist ($BAKPATH$mybasename$BAKEXT)!" + my_exit 4 +fi +if ! [ -f $BAKPATH$mybasename$BAKMD5EXT ] ; then + log_write "$STAG Source backup MD5 does not exist ($BAKPATH$mybasename$BAKMD5EXT)!" + my_exit 5 +fi +# verify if backup is valid +cd $BAKPATH +if [ $? != 0 ]; then + log_write "$STAG change dir to ($BAKPATH) failed." + my_exit 6 +fi +# verifies if md5 is for the expected backup file +md5file=`cat $BAKPATH$mybasename$BAKMD5EXT | awk '{ print $2 }'` +if ! [ "./"$mybasename$BAKEXT == "$md5file" ]; then + log_write "$STAG MD5 ref file is not backup file ($md5file)!" + my_exit 7 +fi +# verifies if md5 is correct +myresult=$(md5sum -c $BAKPATH$mybasename$BAKMD5EXT 2>&1) +myres=$? +if [ $myres != 0 ]; then + log_write "$STAG Checksum invalid" + my_exit 8 +fi +log_write "$STAG Checksum Ok." +my_exit 0 diff --git a/recipes-support/backup-scripts/files/cbackup.sh b/recipes-support/backup-scripts/files/cbackup.sh new file mode 100644 index 0000000..74e1386 --- /dev/null +++ b/recipes-support/backup-scripts/files/cbackup.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# Starts a lower priority version of cbackup +nice -n 5 /usr/bin/.cbackup "$@" diff --git a/recipes-support/backup-scripts/files/checkbk b/recipes-support/backup-scripts/files/checkbk new file mode 100644 index 0000000..852171c --- /dev/null +++ b/recipes-support/backup-scripts/files/checkbk @@ -0,0 +1,193 @@ +#!/bin/sh +# checks all flash partition backup integrity when the expected flash partition is mounted correctly +STAG=checkbk: +PENDINGCHK=/tmp/.boot_pending +# lock wait time max 15mn * 60 = 900 secs (sufficient time to update) +LOCKWAIT=900 +bname=checkbk +TMPBK="" +DEFBAKPATH=/mnt/storage/.sysbackup +_curr_dir="" +configflashuser=/mnt/rom/user +configflashuserbk=$DEFBAKPATH/bk-mnt-rom-user +configflashfactory=/mnt/rom/factory +configflashfactorybk=$DEFBAKPATH/bk-mnt-rom-factory +__USESYSLOG=1 +VERBOSE='' +__EXITCODE=0 + +readonly LOCKFILE_DIR=/var/lock +readonly LOCK_FD=978 + +lock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # still allow to run unlocked if the lock dir does not exist + if [ ! -d "${LOCKFILE_DIR}" ]; then + return 0 + fi + + # create lock file + eval "exec $fd>$lock_file" + # still allow to run unlocked if the lock file cannot be created + if [ $? -ne 0 ]; then + return 0 + fi + + # acquier the lock + flock -w ${LOCKWAIT} $fd \ + && return 0 \ + || return 1 +} + +unlock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # release the lock + flock -u $fd + sync +} + +function my_exit() +{ + cd "$_curr_dir" + unlock $bname + exit $* +} + +function __sig_int { + log_write " " + log_write "$STAG WARNING: SIGINT caught" + my_exit 110 +} + +function __sig_quit { + log_write " " + log_write "$STAG WARNING: SIGQUIT caught" + my_exit 111 +} + +function __sig_term { + log_write " " + log_write "$STAG WARNING: SIGTERM caught" + my_exit 112 +} + +function __sig_hup { + log_write " " + log_write "$STAG WARNING: SIGHUP caught" + my_exit 113 +} + +checkflashpartro() { + if ! grep "$* jffs2 " /proc/mounts | grep -q " ro[,]"; then + return 13 + fi + return 0 +} + +function log_write() +{ + if [ ! -z ${VERBOSE} ] || [ ${__USESYSLOG} -eq 0 ]; then + echo "$*" + fi + if [ ${__USESYSLOG} -ne 0 ] ; then + logger -p local4.info "$*" + fi +} + +function show_help { + echo "checkbk help information:" + echo "Usage: checkbk [ [ [-f file] [-n] ] | [--help] ] " + echo " -d # print debug verbose info" + echo " --help # displays this help information" + echo "example: checkbk; # checks and backup flash partitions silently" + echo "example: checkbk -d; # checks and backup flash partitions with verbose" +} + +if [ -e "${PENDINGCHK}" ]; then + echo "$STAG Pending reboot, could not run!" + exit 97 +fi + +_curr_dir=`pwd` + +# Lock to test a single instance is running, and exit if wait timeout +echo "$STAG Checking if allowed to run..." +lock $bname || ( echo "$STAG Checking if allowed to run... failed"; exit 100 ) +echo "$STAG Checking if allowed to run... done" + +# Set TRAPs to release lock if forced to exit +trap __sig_int SIGINT +trap __sig_quit SIGQUIT +trap __sig_term SIGTERM +trap __sig_hup SIGHUP + +if [ -e "${PENDINGCHK}" ]; then + echo "$TAG Pending reboot, could not run!" + my_exit 97 +fi + +#keeps log file from getting big if run through a cron job +rm /var/log/$LOG_FILE >/dev/null 2>&1 + +TOTALARG=$# +while getopts :d- FLAG; do + case $FLAG in + d ) VERBOSE=1;; + '-') + show_help + my_exit 0;; + \?) + log_write "Invalid option: -$OPTARG" && my_exit 1;; + \:) + log_write "Required argument not found for option: -$OPTARG" && my_exit 2;; + esac +done + +# removes processed option(s) from the cmd line args +shift $((OPTIND-1)) + +log_write "$STAG started" + +# checks if factory partition needs a backup +if checkflashpartro $configflashfactory ; then + log_write "$STAG checking partition ($configflashfactory)" + __CBACKUP_RES=$(cbackup "$configflashfactorybk" 2>&1) + __CBACKUP_RET=$? + log_write "$__CBACKUP_RES" + if test ${__CBACKUP_RET} -ne 0; then + __MBACKUP_RES=$(mbackup "$configflashfactory" 2>&1) + __MBACKUP_RET=$? + log_write "$__MBACKUP_RES" + if test ${__MBACKUP_RET} -ne 0; then + __EXITCODE=$__MBACKUP_RET + fi + fi +else + log_write "$STAG partition ($configflashfactory) is not ready for backup" + __EXITCODE=70 +fi +if checkflashpartro $configflashuser ; then + log_write "$STAG checking partition ($configflashuser)" + __CBACKUP_RES=$(cbackup "$configflashuserbk" 2>&1) + __CBACKUP_RET=$? + log_write "$__CBACKUP_RES" + if test ${__CBACKUP_RET} -ne 0; then + __MBACKUP_RES=$(mbackup "$configflashuser" 2>&1) + __MBACKUP_RET=$? + log_write "$__MBACKUP_RES" + if test ${__MBACKUP_RET} -ne 0; then + __EXITCODE=$__MBACKUP_RET + fi + fi +else + log_write "$STAG partition ($configflashuser) is not ready for backup" + __EXITCODE=71 +fi +log_write "$STAG done!" +my_exit $__EXITCODE diff --git a/recipes-support/backup-scripts/files/checkbk.service b/recipes-support/backup-scripts/files/checkbk.service new file mode 100644 index 0000000..f04783a --- /dev/null +++ b/recipes-support/backup-scripts/files/checkbk.service @@ -0,0 +1,22 @@ +[Unit] +Description=Check flash backups. +DefaultDependencies=no +Before=sysinit.target +After=mountuser.service checkroot.service checkstoragefs.service checkmonolithicupdate.service +Wants=mountuser.service checkroot.service checkstoragefs.service checkmonolithicupdate.service +RequiresMountsFor=/mnt/rom/user +RequiresMountsFor=/mnt/rom/factory +RequiresMountsFor=/tmp +RequiresMountsFor=/run +RequiresMountsFor=/mnt/storage + +[Service] +Type=oneshot +Restart=no +RemainAfterExit=yes +ExecStart=/bin/sh -c 'export _NOSPINDLE=1 ; /usr/bin/checkbk -d ; export _NOSPINDLE= ; ' +StandardOutput=syslog+console +StandardError=syslog+console + +[Install] +WantedBy=multi-user.target diff --git a/recipes-support/backup-scripts/files/checkflash.service b/recipes-support/backup-scripts/files/checkflash.service new file mode 100644 index 0000000..9c552d6 --- /dev/null +++ b/recipes-support/backup-scripts/files/checkflash.service @@ -0,0 +1,25 @@ +[Unit] +Description=Check config flash state. +Before=multi-user.target +Before=shutdown.target +Before=watchdog.service +After=time-sync.target +After=checkbk.service +Wants=checkbk.service +Conflicts=shutdown.target +RequiresMountsFor=/mnt/rom/user +RequiresMountsFor=/tmp +RequiresMountsFor=/run +RequiresMountsFor=/var/volatile + +[Service] +Type=oneshot +Restart=no +RemainAfterExit=yes +TimeoutStartSec=infinity +ExecStart=/usr/bin/checkflashcfg -d +StandardOutput=syslog+console +StandardError=syslog+console + +[Install] +WantedBy=multi-user.target diff --git a/recipes-support/backup-scripts/files/checkflashcfg b/recipes-support/backup-scripts/files/checkflashcfg new file mode 100644 index 0000000..0de01a1 --- /dev/null +++ b/recipes-support/backup-scripts/files/checkflashcfg @@ -0,0 +1,269 @@ +#!/bin/sh +# checks boot options to see what to do when the system has a flash configuration corruption +STAG=checkflashcfg: +PENDINGCHK=/tmp/.boot_pending +# lock wait time max 15mn * 60 = 900 secs (sufficient time to check it) +LOCKWAIT=900 +bname=checkflashcfg +_curr_dir="" +__USESYSLOG=1 +VERBOSE='' +__EXITCODE=0 +CONFIGMOUNT=/mnt/rom/user +CONFIGMOUNTTYPE=jffs2 +DEVCONFIG=/dev/mtdblock9 +tempdir="" +TMPMOUNT=/tmp/.mnt_config +__NOHANG=0 +_RECOVERY=1 + +readonly LOCKFILE_DIR=/var/lock +readonly LOCK_FD=977 + +# Get boot options configuration file +if [ -f "/etc/bootoptions.conf" ]; then + source "/etc/bootoptions.conf" +fi + +lock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # still allow to run unlocked if the lock dir does not exist + if [ ! -d "${LOCKFILE_DIR}" ]; then + return 0 + fi + + # create lock file + eval "exec $fd>$lock_file" + # still allow to run unlocked if the lock file cannot be created + if [ $? -ne 0 ]; then + return 0 + fi + + # acquier the lock + flock -w ${LOCKWAIT} $fd \ + && return 0 \ + || return 1 +} + +unlock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # release the lock + flock -u $fd + sync +} + +function my_exit() +{ + trap - SIGINT + trap - SIGQUIT + trap - SIGTERM + trap - SIGHUP + sync + if [ -d "${tempdir}" ]; then + if mount | grep -q "${tempdir}"; then + umount "$tempdir" + fi + rmdir "$tempdir" + fi + cd "$_curr_dir" + unlock $bname + exit $* +} + +checkrecovery() { + if mount | grep -q "on / type nfs" ; then + return 0 + else + return 1 + fi +} + +function __sig_int { + log_write " " + log_write "$STAG WARNING: SIGINT caught" + my_exit 110 +} + +function __sig_quit { + log_write " " + log_write "$STAG WARNING: SIGQUIT caught" + my_exit 111 +} + +function __sig_term { + log_write " " + log_write "$STAG WARNING: SIGTERM caught" + my_exit 112 +} + +function __sig_hup { + log_write " " + log_write "$STAG WARNING: SIGHUP caught" + my_exit 113 +} + +checkflashconfig() { + if ! grep -q "$* " /proc/mounts; then + return 14 + fi + return 0 +} + +function log_write() +{ + if [ ! -z ${VERBOSE} ] || [ ${__USESYSLOG} -eq 0 ]; then + echo "$*" + fi + if [ ${__USESYSLOG} -ne 0 ] ; then + logger -p local4.info "$*" + fi +} + +function show_help { + echo "checkflashcfg help information:" + echo "Usage: checkflashcfg [ [ [-d] [-n] ] | [--help] ]" + echo "Verify boot options and flash config state to learn what to do when corrupted" + echo "WARNING: this script may intentionnaly hang if -n is not provided and flash is corrupted" + echo " if not hanging, it may attempt to recreate an unmountable corrupted flash" + echo " config partition" + echo " -d # print debug verbose info" + echo " -n # no hang even if boot option specifies blocking in corruption" + echo " --help # displays this help information" + echo "example: checkflashcfg; # checks flash corruption and boot options silently" + echo "example: checkflashcfg -d -n;# checks flash corruption and boot options verbose, no hang" +} + +if [ -e "${PENDINGCHK}" ]; then + echo "$STAG Pending reboot, could not run!" + exit 97 +fi + +_curr_dir=`pwd` + +# Lock to test a single instance is running, and exit if wait timeout +echo "$STAG Checking if allowed to run..." +lock $bname || ( echo "$STAG Checking if allowed to run... failed"; exit 100 ) +echo "$STAG Checking if allowed to run... done" + +# Set TRAPs to release lock if forced to exit +trap __sig_int SIGINT +trap __sig_quit SIGQUIT +trap __sig_term SIGTERM +trap __sig_hup SIGHUP + +if [ -e "${PENDINGCHK}" ]; then + echo "$STAG Pending reboot, could not run!" + my_exit 97 +fi + +#keeps log file from getting big +rm /var/log/$LOG_FILE >/dev/null 2>&1 + +TOTALARG=$# +while getopts :dn- FLAG; do + case $FLAG in + d ) VERBOSE=1;; + n ) __NOHANG=1;; + '-') + show_help + my_exit 0;; + \?) + log_write "Invalid option: -$OPTARG" && my_exit 1;; + \:) + log_write "Required argument not found for option: -$OPTARG" && my_exit 2;; + esac +done + +# removes processed option(s) from the cmd line args +shift $((OPTIND-1)) + +log_write "$STAG checking..." + +# checks if user flash is mounted correctly +if ! checkflashconfig "$CONFIGMOUNT" "$CONFIGMOUNTTYPE" ; then + # verifies if in recovery mode + checkrecovery + _RECOVERY=$? + # checks if the block boot option is active from bootoptions.conf + if [ ${BLOCKOPTION} -eq 1 ]; then + if [ ${__NOHANG} -ne 1 ]; then + if [ $_RECOVERY -eq 0 ]; then + log_write "$STAG script process is blocked as flash config is in recovery mode!" + else + log_write "$STAG script process is blocked as flash config needs to be repaired!" + fi + _MYCOUNTER=0 + # makes sure the watchdog is manually started as systemd booting seq would be stuck to our process + /etc/init.d/watchdog.sh start + #loops forever to make sure any dependant service won't start when booting + while [ $_MYCOUNTER -eq 0 ]; do + sleep 1s + done + else + if [ $_RECOVERY -ne 0 ]; then + log_write "$STAG flash config needs to be repaired!" + __EXITCODE=3 + fi + fi + else + if [ $_RECOVERY -ne 0 ]; then + # checks if flash could be mounted correctly + tempdir=`mktemp -d` + if [ $? -ne 0 ]; then + log_write "$STAG could not create tmp directory!" + my_exit 4 + fi + if ! mount -t ${CONFIGMOUNTTYPE} -o ro,noatime,sync ${DEVCONFIG} ${tempdir}; then + # we need to recreate flash content cause the system could not self warns the problem + # and the flash is not mountable + log_write "$STAG recreating configuration flash partition..." + _C_RES=$(flash_erase -j /dev/mtd9 0 0 2>&1) + _C_RET=$? + if [ $_C_RET -ne 0 ]; then + log_write "Warning: cannot recreate flash partition!" + __EXITCODE=5 + else + log_write "$STAG recreating configuration flash partition... Done" + # attempt to use mountuser tool to get flash access + _C_RES=$(/usr/bin/mountuser rw 2>&1) + _C_RET=$? + if [ $_C_RET -eq 0 ]; then + log_write "$STAG recreating config flash partition content..." + cp -rf $CONFIGMOUNT/* $TMPMOUNT + if [ $? -ne 0 ]; then + log_write "Warning: cannot copy current config to flash mount!" + __EXITCODE=6 + else + echo "---------------------------" >> $TMPMOUNT/config/motd + echo "Attempted to recreate Flash" >> $TMPMOUNT/config/motd + echo "---------------------------" >> $TMPMOUNT/config/motd + _C_RES=$(/usr/bin/mountuser ro 2>&1) + _C_RET=$? + if [ $_C_RET -ne 0 ]; then + log_write "Warning: cannot remount flash mount to read only!" + __EXITCODE=7 + else + log_write "$STAG recreating config flash partition content... Done" + fi + fi + else + log_write "$STAG cannot access flash for rw access!" + __EXITCODE=8 + fi + fi + else + log_write "$STAG flash is mountable, won't be automatically repaired!" + __EXITCODE=9 + fi + fi + fi +fi + +log_write "$STAG checking... Done" +my_exit $__EXITCODE diff --git a/recipes-support/backup-scripts/files/mbackup b/recipes-support/backup-scripts/files/mbackup new file mode 100644 index 0000000..29acd21 --- /dev/null +++ b/recipes-support/backup-scripts/files/mbackup @@ -0,0 +1,444 @@ +#!/bin/sh +# Define this variable _NOSPINDLE before calling this script if this script run through a systemd service +# if this variable _SAFESYNC is also defined, it will do a wd safe sync instead (when watchdog daemon is not used) + +STAG=mbackup: +ENDSIG=/tmp/mbackup_sig +ERRSIG=/tmp/mbackup_err +PENDINGCHK=/tmp/.boot_pending +# lock wait time max 15mn * 60 = 900 secs (sufficient time to update) +LOCKWAIT=900 +bname=mbackup +TMPBK="" +DEFBAKPATH=/mnt/storage/.sysbackup/ +BAKPATH=$DEFBAKPATH +_curr_dir="" +BAKEXT=".tar.gz" +PREVEXT=".tar.gz.bk1" +TMPEXT=".tar.gz.tmp" +BAKMD5EXT=".md5" +PREVMD5EXT=".md5.bk1" +TMPMD5EXT=".md5.tmp" +mybasename="" +CREATEPBACK=1 + +sp="/-\|" +sc=0 +spin() { + if [ -z "$_NOSPINDLE" ]; then + printf "\r${STAG} ${sp:sc++:1}" + ((sc==${#sp})) && sc=0 + else + printf "${STAG} ${sp:sc++:1} \n" + ((sc==${#sp})) && sc=0 + if [ ! -z "$_SAFESYNC" ]; then + dmesg -D + echo 1 > /dev/watchdog + dmesg -E + fi + fi +} +endspin() { + if [ -z "$_NOSPINDLE" ]; then + printf "\r" + else + if [ ! -z "$_SAFESYNC" ]; then + dmesg -E + fi + fi +} + +readonly LOCKFILE_DIR=/var/lock +readonly LOCK_FD=980 + +lock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # still allow to run unlocked if the lock dir does not exist + if [ ! -d "${LOCKFILE_DIR}" ]; then + return 0 + fi + + # create lock file + eval "exec $fd>$lock_file" + # still allow to run unlocked if the lock file cannot be created + if [ $? -ne 0 ]; then + return 0 + fi + + # acquier the lock + flock -w ${LOCKWAIT} $fd \ + && return 0 \ + || return 1 +} + +unlock() { + local prefix=$1 + local fd=${2:-$LOCK_FD} + local lock_file=$LOCKFILE_DIR/$prefix.lock + + # release the lock + flock -u $fd + sync +} + +function my_exit() +{ + sync + if [ -f "$BAKPATH$mybasename$TMPEXT" ]; then + rm -f $BAKPATH$mybasename$TMPEXT + fi + if [ -f "$BAKPATH$mybasename$TMPMD5EXT" ]; then + rm -f $BAKPATH$mybasename$TMPMD5EXT + fi + if [ -d "${TMPBK}" ]; then + TMPBKMNT_RES=$(mount | grep "${TMPBK}") + TMPBKMNT_RET=$? + if [ $TMPBKMNT_RET -eq 0 ]; then + umount ${TMPBK} + fi + rmdir "${TMPBK}" + fi + sync + cd "$_curr_dir" + unlock $bname + exit $* +} + +function __sig_int { + endspin + log_write " " + log_write "$STAG WARNING: SIGINT caught" + my_exit 110 +} + +function __sig_quit { + endspin + log_write " " + log_write "$STAG WARNING: SIGQUIT caught" + my_exit 111 +} + +function __sig_term { + endspin + log_write " " + log_write "$STAG WARNING: SIGTERM caught" + my_exit 112 +} + +function __sig_hup { + endspin + log_write " " + log_write "$STAG WARNING: SIGHUP caught" + my_exit 113 +} + +function log_write() +{ + echo "$*" +} + +function log_write_nr() +{ + echo -n "$*" +} + +function show_help { + log_write "mbackup help information:" + log_write "Usage: mbackup [ [ [-f file] [-n] ] | [--help] ] " + log_write " where: # source directory path to backup recursively" + log_write " options: -f file # force output file name (will be appended with .tar.gz/.md5)" + log_write " # specified file destination directory must exist!" + log_write " # if -f not used, default dest. dir. is created: $BAKPATH" + log_write " # with auto generated filename according to " + log_write " -n # do not create a previous backup (*.bk1) if one already exist" + log_write " # default is to create one" + log_write " --help # displays this help information" + log_write "example: mbackup /mnt/rom/user; # backup user flash configuration to default dir" + log_write "example: mbackup -f /tmp/qq /mnt/rom/user; # backup user flash configuration to /tmp/qq" +} + +function create_basename() +{ + local retval + local retval2 + local repchr=- + local srcchr=/ + local slen=${#1} + local mystr + local mystr2 + if [ "${1:$slen - 1:1}" == "/" ] ; then + mystr=${1:0:$slen - 1} + slen=$((slen-1)) + else + mystr=$1 + fi + if [ ${1:0:1} == "/" ] ; then + mystr2=${mystr:1:$slen - 1} + slen=$((slen-1)) + else + mystr2=$mystr + fi + retval="bk-"${mystr2//$srcchr/$repchr} + retval2=${retval// /$repchr} + echo $retval2 +} + +# returns the file basename without directory and extension +function get_basename() +{ + echo ${1//+(*\/|.*)} + return 0 +} + +function check_destpath() +{ + local retval=0 + local slen=${#1} + local mystr + if ! [ -d $1 ] ; then + log_write "$STAG Destination directory does not exist ($1)!" + retval=80 + else + if [ "${1:$slen - 1:1}" == "/" ] ; then + mystr=${1:0:$slen - 1} + slen=$((slen-1)) + else + mystr=$1 + fi + BAKPATH=$mystr"/" + fi + return $retval +} + +# corrects md5 associated source file +# param1=originalfilename +# param2=newfilename +# param3=md5 file to correct +function correct_md5_file() +{ + local name1 + local name2 + name1=`basename $1` + if [ $? -ne 0 ]; then + log_write "$STAG Getting basename of ($1) fail!" + return 81 + fi + name2=`basename $2` + if [ $? -ne 0 ]; then + log_write "$STAG Getting basename of ($2) fail!" + return 82 + fi + sed -i "s/$name1/$name2/g" $3 + if [ $? -ne 0 ]; then + log_write "$STAG Sed md5 file ($3) fail!" + return 83 + fi + return 0 +} + +if [ -e "${PENDINGCHK}" ]; then + log_write "$STAG Pending reboot, could not run!" + exit 97 +fi + +_curr_dir=`pwd` + +# Lock to test a single instance is running, and exit if wait timeout +log_write "$STAG Checking if allowed to run..." +lock $bname || ( log_write "$STAG Checking if allowed to run... failed"; exit 100 ) +log_write "$STAG Checking if allowed to run... done" + +# Set TRAPs to release lock if forced to exit +trap __sig_int SIGINT +trap __sig_quit SIGQUIT +trap __sig_term SIGTERM +trap __sig_hup SIGHUP + +if [ -e "${PENDINGCHK}" ]; then + log_write "$TAG Pending reboot, could not run!" + my_exit 97 +fi + +TOTALARG=$# +while getopts :f:n- FLAG; do + case $FLAG in + f) + #log_write "#Filename (-f)" + check_destpath `dirname "$OPTARG"` + valret=$? + if [ $valret -ne 0 ]; then + my_exit $valret + fi + mybasename=`basename "$OPTARG"`;; + n) + log_write "$STAG No previous backup option specified (-n)" + CREATEPBACK=0;; + '-') + show_help + my_exit 0;; + \?) + log_write "Invalid option: -$OPTARG" && my_exit 1;; + \:) + log_write "Required argument not found for option: -$OPTARG" && my_exit 2;; + esac +done + +# removes processed option(s) from the cmd line args +shift $((OPTIND-1)) + +if [ "$#" -ne 1 ]; then + show_help + my_exit 3 +fi + +if ! [ -d $1 ] ; then + log_write "$STAG Source directory does not exist ($1)!" + my_exit 4 +fi +if [ "x$mybasename" == "x" ] ; then + mybasename=$(create_basename $1) + if ! [ -d "$BAKPATH" ]; then + mkdir -p $BAKPATH + if [ $? -ne 0 ]; then + log_write "$STAG create dir ($BAKPATH) fail!" + my_exit 5 + fi + fi +fi + +log_write "$STAG Creating backup to: "$BAKPATH$mybasename +TMPBK=$(mktemp -d) +if [ $? -ne 0 ]; then + log_write "$STAG mktemp fail!" + my_exit 6 +fi + +# temporarily bind mount dir to backup to TMPBK +mount --bind -o ro $1 ${TMPBK} +if [ $? -ne 0 ]; then + log_write "$STAG mount $1 to temp folder fail!" + my_exit 7 +fi + +rm -f $BAKPATH$mybasename$TMPEXT +if [ $? -ne 0 ]; then + log_write "$STAG cannot remove ($BAKPATH$mybasename$TMPEXT)!" + my_exit 8 +fi +rm -f $BAKPATH$mybasename$TMPMD5EXT +if [ $? -ne 0 ]; then + log_write "$STAG cannot remove ($BAKPATH$mybasename$TMPMD5EXT)!" + my_exit 9 +fi +rm -f ${ENDSIG} +rm -f ${ERRSIG} +log_write "$STAG Creating files backup..." +( +tar -zcf $BAKPATH$mybasename$TMPEXT -C ${TMPBK} . +if [ $? -ne 0 ]; then + log_write " $STAG tar ($BAKPATH$mybasename$TMPEXT) fail!" + touch ${ERRSIG} + exit 10 +fi +touch ${ENDSIG} +) & +until [ -f ${ENDSIG} ]; do + spin + if [ -f ${ERRSIG} ]; then + my_exit 11 + fi + if [ ! -f ${ENDSIG} ]; then + sleep 1s + fi +done +endspin +log_write "$STAG Creating files backup... done" + +# create md5 +cd $BAKPATH +if [ $? -ne 0 ]; then + log_write "$STAG cannot change dir to ($BAKPATH)!" + my_exit 12 +fi +md5sum ./$mybasename$TMPEXT > ./$mybasename$TMPMD5EXT +if [ $? -ne 0 ]; then + log_write "$STAG cannot create md5 for ($BAKPATH$mybasename$TMPEXT)!" + my_exit 13 +fi + +# create a previous backup if one already exit +if [ $CREATEPBACK -eq 1 ]; then + if [ -f "$BAKPATH$mybasename$BAKEXT" ] && [ -f "$BAKPATH$mybasename$BAKMD5EXT" ]; then + log_write "$STAG Copy prev. backup to: "$BAKPATH$mybasename$PREVEXT + cp -f $BAKPATH$mybasename$BAKEXT $BAKPATH$mybasename$PREVEXT + if [ $? -ne 0 ]; then + log_write "$STAG Creating previous backup ($BAKPATH$mybasename$PREVEXT) fail!" + my_exit 14 + fi + log_write "$STAG Copy prev. MD5 to: "$BAKPATH$mybasename$PREVMD5EXT + cp -f $BAKPATH$mybasename$BAKMD5EXT $BAKPATH$mybasename$PREVMD5EXT + if [ $? -ne 0 ]; then + log_write "$STAG Creating previous backup ($BAKPATH$mybasename$PREVMD5EXT) fail!" + my_exit 15 + fi + correct_md5_file $BAKPATH$mybasename$BAKEXT $BAKPATH$mybasename$PREVEXT $BAKPATH$mybasename$PREVMD5EXT + if [ $? -ne 0 ]; then + my_exit $? + fi + fi +fi + +# create current backup from temporary files +rm -f $BAKPATH$mybasename$BAKEXT +if [ $? -ne 0 ]; then + log_write " $STAG cannot remove ($BAKPATH$mybasename$BAKEXT) fail!" + my_exit 16 +fi +rm -f $BAKPATH$mybasename$BAKMD5EXT +if [ $? -ne 0 ]; then + log_write " $STAG cannot remove ($BAKPATH$mybasename$BAKMD5EXT) fail!" + my_exit 17 +fi +log_write "$STAG Move backup to: "$BAKPATH$mybasename$BAKEXT +mv $BAKPATH$mybasename$TMPEXT $BAKPATH$mybasename$BAKEXT +if [ $? -ne 0 ]; then + log_write " $STAG cannot move to ($BAKPATH$mybasename$BAKEXT) fail!" + my_exit 18 +fi +log_write "$STAG Move MD5 to: "$BAKPATH$mybasename$BAKMD5EXT +mv $BAKPATH$mybasename$TMPMD5EXT $BAKPATH$mybasename$BAKMD5EXT +if [ $? -ne 0 ]; then + log_write " $STAG cannot move to ($BAKPATH$mybasename$BAKMD5EXT) fail!" + my_exit 19 +fi +correct_md5_file $BAKPATH$mybasename$TMPEXT $BAKPATH$mybasename$BAKEXT $BAKPATH$mybasename$BAKMD5EXT +if [ $? -ne 0 ]; then + my_exit $? +fi +rm -f ${ENDSIG} +rm -f ${ERRSIG} +log_write "$STAG System sync..." +( +sync +if [ $? -ne 0 ]; then + log_write " $STAG sync fail!" + touch ${ERRSIG} + exit 20 +fi +touch ${ENDSIG} +) & +until [ -f ${ENDSIG} ]; do + spin + if [ -f ${ERRSIG} ]; then + my_exit 21 + fi + if [ ! -f ${ENDSIG} ]; then + sleep 1s + fi +done +endspin +log_write "$STAG System sync... done" +my_exit 0 diff --git a/recipes-support/backup-scripts/files/mbackup.sh b/recipes-support/backup-scripts/files/mbackup.sh new file mode 100644 index 0000000..850de84 --- /dev/null +++ b/recipes-support/backup-scripts/files/mbackup.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# Starts a lower priority version of mbackup +nice -n 5 /usr/bin/.mbackup "$@"