mir3c/squashfs-root/lib/preinit/90_mount_bind_etc

198 lines
4.7 KiB
Bash
Executable File

#!/bin/sh
# Copyright (C) 2006-2010 OpenWrt.org
# Copyright (C) 2010 Vertical Communications
# When we failed mount /data, the whole mtd partition will be automatically erased by "mtd erase overlay"
# thus we lose all config files. here we try to save the day
do_data_mount_fail_recover() {
local rec_mtd_name="cfg_bak"
[ -f /tmp/need_config_recovery ] || return 0
rm -f /tmp/need_config_recovery
rec_mtd=$(find_mtd_part "$rec_mtd_name")
[ -z "$rec_mtd" ] && return 0
dd if="$rec_mtd" of=/tmp/head.bin bs=4 count=1
head=`hexdump -e '1/4 "%.6x"' /tmp/head.bin`
[ "$head" = "088b1f" ] || return 0
#found a valid gzip header
echo "Data fail etc recover..."
dd if="$rec_mtd" of=/tmp/rec.tar.gz bs=2048
mkdir -p /tmp/tmpconfig
tar -xzf /tmp/rec.tar.gz -C /tmp/tmpconfig
[ "$?" = "0" ] || {
echo "Fail to extract backup config"
return 0
}
cp -rf /tmp/tmpconfig/etc/config/* /etc/config/
rm -rf /tmp/tmpconfig/etc/config
}
# Check uci config files in /etc/config/. Corrupted uci configs could cause uci deadloop
# Recovery sequence:
# 1. from mtd cfg_bak partition [TBD]
# 2. from the other system's config (/data/etc_bak)
# 3. from rootfs
do_uci_config_integrity_check() {
for file in `find /data/etc/config -type f`
do
cat $file > /dev/null
[ "$?" = "0" ] && continue
[ -d /data/etc_bak ] && {
bakfile=`echo $file | sed "s/\/data\/etc/\/data\/etc_bak/g"`
[ -f "$bakfile" ] && {
rm -f $file
cp $bakfile $file
echo Recover $file from the other system
continue
}
}
rootfs_file=`echo $file | sed "s/\/data\/etc/\/etc/g"`
[ -f "$rootfs_file" ] && {
rm -f $file
cp $rootfs_file $file
echo Recover $file from rootfs
continue
}
# Can't recover. Remove the file to prevent trouble.
rm -f $file
done
}
do_recovery_config() {
if [ ! -f /etc/remove.conf ]
then
echo " ************* WARNING *******************"
echo " ***** /rom/etc/remove.conf no exist and try to rsync files ****"
else
echo " *****ota: remove files in /etc/remove.conf *****"
cat /etc/remove.conf | xargs rm -rf
fi
echo N | cp -ri /etc/* /data/etc 2>/dev/null
}
# Process /etc under different scenario
# Return 1 if OTA scenario. otherwise return 0
process_etc() {
# for: 1, ota; 2, format disk; 3, downgrade
mkdir -p /data/etc
flag_name=`uci get misc.mount_bind_etc.flag_name`
flg_ota=`nvram get flag_ota_reboot`
flg_format=`nvram get $flag_name`
curr_os=`nvram get flag_boot_rootfs`
[ -z "$curr_os" ] && curr_os=0
bkup_os=$((1-$curr_os))
if [ "$flg_format" = "1" ]; then
# /data is fresh formated. simply make a copy of /etc
rm -rf /data/etc
cp -prf /etc /data/etc
nvram unset $flag_name
nvram unset flag_recover_config
nvram commit
return 0
fi
# check if we are with correct etc files
if [ "$flg_ota" = "0" ]; then
flg_try_sys1=`nvram get flag_try_sys1_failed`
flg_try_sys2=`nvram get flag_try_sys2_failed`
# if any fail flag is set, we might need etc recovery
if [ "$flg_try_sys1" = "1" -o "$flg_try_sys2" = "1" ]; then
echo "System fail flag set. Do etc recovery"
else
return 0
fi
if [ ! -d /data/etc_bak ]; then
echo " WARNING: No etc_bak folder"
do_recovery_config
return 0
fi
if [ `ls /data/etc_bak | wc -l` -eq 0 ]; then
echo " ERROR: Empty backup etc"
rm -rf /data/etc_bak
do_recovery_config
return 0
fi
if [ -f "/data/etc_bak/with_os_0" -a -f "/data/etc_bak/with_os_1" ]; then
# something is wrong. assume etc bak is corrupt
echo " ERROR: Confusing with etc OS flags"
rm -rf /data/etc_bak
do_recovery_config
return 0
fi
# if backup etc OS number match with current OS number, switch etc
if [ -f /data/etc_bak/with_os_"$curr_os" ]; then
echo " Use backup etc"
mv /data/etc /data/etc_tmp
mv /data/etc_bak /data/etc
mv /data/etc_tmp /data/etc_bak
rm -f /data/etc_bak/with_os*
touch /data/etc_bak/with_os_"$bkup_os"
fi
return 0
fi
if [ "$flg_ota" = "1" ]; then
/usr/sbin/config_pre_ota.sh
do_recovery_config
return 1
fi
return 0
}
do_mount_bind_etc() {
process_etc
post_ota="$?"
#replace files that size 0 in /data/etc
cd /data/etc
find . -size 0 | while read line
do
if [ -s /etc/$line -a -f /etc/$line ]; then
echo "/etc damaged, recovering /etc/$line"
cp -arf /etc/$line /data/etc/$line
fi
done
cd /
sync
# Do uci conf integrity checks before we mount.bind /etc
do_uci_config_integrity_check
mount --bind /data/etc /etc
rm -f /etc/with_os*
touch /etc/with_os_"$curr_os"
do_data_mount_fail_recover
if [ "$post_ota" = "1" ] ; then
/usr/sbin/config_post_ota.sh
fi
[ -s /tmp/.uci.disk ] && uci import -f /tmp/.uci.disk && rm -f /tmp/.uci.disk
[ -f /etc/sysdisk ] && cp -f /etc/sysdisk /tmp/sysdisk
}
boot_hook_add preinit_main do_mount_bind_etc