summaryrefslogtreecommitdiffstats
path: root/rescue/Flash
diff options
context:
space:
mode:
Diffstat (limited to 'rescue/Flash')
-rwxr-xr-xrescue/Flash/scripts/backup_systemloop106
-rwxr-xr-xrescue/Flash/scripts/clear_systemloop87
-rw-r--r--rescue/Flash/scripts/rescue_common146
-rwxr-xr-xrescue/Flash/scripts/reset_rootpass100
-rwxr-xr-xrescue/Flash/scripts/reset_userpass111
-rwxr-xr-xrescue/Flash/scripts/restore_systemloop167
-rwxr-xr-xrescue/Flash/scripts/test_badblocks69
-rwxr-xr-xrescue/Flash/scripts/upgrade196
-rwxr-xr-xrescue/Flash/scripts/upgrade.merge-users52
9 files changed, 1034 insertions, 0 deletions
diff --git a/rescue/Flash/scripts/backup_systemloop b/rescue/Flash/scripts/backup_systemloop
new file mode 100755
index 000000000..65c3185e6
--- /dev/null
+++ b/rescue/Flash/scripts/backup_systemloop
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ mkdir -p $rootdir
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ if [ x"$version" = x"1.0" ]; then
+ mkdir -p $tmpdir/shared
+ if ! mount_sharedroot $tmpdir/shared; then
+ return 1
+ fi
+ fi
+
+ if [ ! -d $dir ]; then
+ mkdir $dir
+ fi
+
+ return 0
+}
+
+function doit() {
+
+ clear
+ echo
+ echo -n 'Creating backup file. This can take some time: '
+
+ bzip2 -c $loop > $target 2> /tmp/rescue-backup.err &
+
+ sleep 2
+
+ while ps | grep -q bzip2; do
+ progress
+ done
+
+ sync
+
+ echo
+ echo
+
+ errsize=$(ls -la /tmp/rescue-backup.err | cut -d' ' -f5)
+ if [ $errsize -ne 0 ]; then
+ echo "Error compressing user files into $target"
+ return 1
+ else
+ echo 'Backup file created!'
+ fi
+
+ echo
+
+ return 0
+}
+
+function cleanup() {
+
+ if [ x"$version" = x"1.0" ]; then
+ umount $tmpdir/shared > /dev/null 2>&1
+ rmdir $tmpdir/shared
+ fi
+
+ umount $rootdir > /dev/null 2>&1
+ rmdir $rootdir $tmpdir 2> /dev/null
+
+ return 0
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ dir="$tmpdir/shared/backup"
+ loop="$rootdir/loopbacks/system.loop"
+else
+ dir="$rootdir/backup"
+ loop="$rootdir/.loopbacks/system.loop"
+fi
+
+file="backup-$(date +%Y%m%d).bz2"
+target="$dir/$file"
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
+exit 0
diff --git a/rescue/Flash/scripts/clear_systemloop b/rescue/Flash/scripts/clear_systemloop
new file mode 100755
index 000000000..f218d0987
--- /dev/null
+++ b/rescue/Flash/scripts/clear_systemloop
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ mkdir -p $rootdir
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ return 0
+}
+
+function doit() {
+
+ clear
+ echo
+ echo "WARNING!"
+ echo
+ echo "Mandriva Flash will be reseted to factory defaults!"
+ echo -n "All user files, customizations and new packages installed "
+ echo "will be removed."
+ echo
+ echo -n "Do you want to continue? [N/y] "
+ read confirm
+
+ if [ x"$confirm" = x"y" -o x"$confirm" = x"Y" ]; then
+
+ if [ ! -f $loop ]; then
+ dd if=/dev/zero of=$loop bs=4000000 count=100
+ fi
+
+ if [ x"$version" = x"1.0" ]; then
+ /sbin/mkfs.ext2 -q -F $loop
+ fi
+
+ echo
+ if [ $? -ne 0 ]; then
+ echo 'Error reseting device to factory defaults'
+ return 1
+ else
+ echo 'Mandriva Flash was restored to factory defaults!'
+ fi
+ fi
+
+ echo
+
+ return 0
+}
+
+function cleanup() {
+
+ umount $rootdir > /dev/null 2>&1
+ rmdir $rootdir $tmpdir 2> /dev/null
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ loop="$rootdir/loopbacks/system.loop"
+else
+ loop="$rootdir/.loopbacks/system.loop"
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
diff --git a/rescue/Flash/scripts/rescue_common b/rescue/Flash/scripts/rescue_common
new file mode 100644
index 000000000..d09a3de1c
--- /dev/null
+++ b/rescue/Flash/scripts/rescue_common
@@ -0,0 +1,146 @@
+#!/bin/bash
+
+function detect_version() {
+
+ _tmpdir="/tmp/$$"
+
+ mkdir -p $_tmpdir
+
+ nash --force > /dev/null 2>&1 <<EOF
+mount -t vfat LABEL=Share $_tmpdir
+EOF
+ if [ $? -eq 0 ]; then
+ version="1.0"
+ else
+ version="1.05"
+ fi
+
+ umount $_tmpdir 2> /dev/null
+ rmdir $_tmpdir 2> /dev/null
+}
+
+function check_vendor() {
+
+ # list of supported vendors/models
+
+ # mandriva flash 1.0 (france)
+ vendors[0]="13fe"
+ models[0]="1a00"
+ # mandriva flash 1.0 (brazil)
+ vendors[1]="0930"
+ models[1]="653e"
+ # mandriva flash 4GB (france)
+ vendors[2]="13fe"
+ models[2]="1d00"
+
+ rc=1
+
+ mount -t usbfs none /proc/bus/usb
+
+ i=0
+ while [ ! -z "${vendors[$i]}" ]; do
+
+ grep "P:" /proc/bus/usb/devices | grep -q \
+ "Vendor=${vendors[$i]} ProdID=${models[$i]}"
+ if [ $? -eq 0 ]; then
+ rc=0
+ break
+ fi
+
+ let i++
+ done
+
+ umount /proc/bus/usb
+
+ return $rc
+}
+
+function insert_pendrive() {
+
+ _tmpdir="/tmp/rescue-temp"
+ mkdir -p $_tmpdir
+
+ modprobe usb-storage > /dev/null 2>&1
+ modprobe vfat > /dev/null 2>&1
+
+ echo
+ echo -n 'Please insert your Mandriva Flash pen drive and press ENTER when ready: '
+ read READY
+ echo
+ echo -n 'Detecting pen drive: '
+
+ for ((i=0; $i <= 15 ; i++)); do
+ nash --force > /dev/null 2>&1 <<EOF
+mount -t vfat LABEL=MDVUSBROOT $_tmpdir
+EOF
+ if [ $? -ne 0 ]; then
+ echo -n '.'
+ sleep 1
+ else
+ echo -n ' found!'
+
+ if ! check_vendor; then
+ echo
+ echo "This is not an official Mandriva Flash key!"
+ echo
+ fi
+
+ cat /proc/mounts | grep $_tmpdir | cut -d' ' -f1 | \
+ sed 's/[0-9]*$//g' > /tmp/rescue-device
+ umount $_tmpdir
+ rmdir $_tmpdir 2> /dev/null
+
+ detect_version
+
+ return 0
+ fi
+ done
+
+ rmdir $_tmpdir 2> /dev/null
+
+ echo
+ echo
+ echo "Couldn't detect Mandriva Flash pen drive!"
+ echo
+
+ return 1
+}
+
+function mount_usbroot() {
+
+ nash --force > /dev/null 2>&1 <<EOF
+mount -t vfat LABEL=MDVUSBROOT $1
+EOF
+ if [ $? -ne 0 ]; then
+ echo "Error mounting device labeled MDVUSBROOT"
+ return 1
+ fi
+
+ return 0
+}
+
+function mount_sharedroot() {
+
+ nash --force > /dev/null 2>&1 <<EOF
+mount -t vfat LABEL=Share $1
+EOF
+ if [ $? -ne 0 ]; then
+ echo "Error mounting device labeled Share"
+ return 1
+ fi
+
+ return 0
+}
+
+function progress() {
+
+ echo -ne '\b|'
+ usleep 100000
+ echo -ne '\b/'
+ usleep 100000
+ echo -ne '\b-'
+ usleep 100000
+ echo -ne '\b\\'
+ usleep 100000
+}
+
diff --git a/rescue/Flash/scripts/reset_rootpass b/rescue/Flash/scripts/reset_rootpass
new file mode 100755
index 000000000..c0a505f21
--- /dev/null
+++ b/rescue/Flash/scripts/reset_rootpass
@@ -0,0 +1,100 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ modprobe unionfs > /dev/null 2>&1
+ modprobe squashfs > /dev/null 2>&1
+ modprobe loop > /dev/null 2>&1
+
+ mkdir -p $rootdir
+ mkdir -p $tmpdir/squash
+ mkdir -p $tmpdir/user
+ mkdir -p $tmpdir/union
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ mount -t squashfs -o loop $sfs_loop $tmpdir/squash > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting distrib.sqfs"
+ return 1
+ fi
+
+ mount -t ext2 -o loop $sys_loop $tmpdir/user > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting system.loop"
+ return 1
+ fi
+
+ mount -t unionfs -o dirs=$tmpdir/user=rw:$tmpdir/squash=ro \
+ none $tmpdir/union
+ if [ $? -ne 0 ]; then
+ echo "Error creating union of distrib.sqfs and system.loop"
+ return 1
+ fi
+
+ chroot $tmpdir/union /etc/init.d/keytable start &> /dev/null
+ chroot $tmpdir/union /usr/bin/unicode_start
+
+ return 0
+}
+
+function doit() {
+
+ clear
+ echo
+ chroot $tmpdir/union passwd root
+ echo
+ echo
+
+ return 0
+}
+
+function cleanup() {
+
+ chroot $tmpdir/union /usr/bin/unicode_stop
+
+ umount $tmpdir/union > /dev/null 2>&1
+ umount $tmpdir/user > /dev/null 2>&1
+ umount $tmpdir/squash > /dev/null 2>&1
+ umount $rootdir > /dev/null 2>&1
+
+ rmdir $tmpdir/union $tmpdir/user $tmpdir/squash 2> /dev/null
+ rmdir $rootdir $tmpdir 2> /dev/null
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ sys_loop="$rootdir/loopbacks/system.loop"
+ sfs_loop="$rootdir/loopbacks/distrib.sqfs"
+else
+ sys_loop="$rootdir/.loopbacks/system.loop"
+ sfs_loop="$rootdir/.loopbacks/distrib.sqfs"
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
+exit 0
diff --git a/rescue/Flash/scripts/reset_userpass b/rescue/Flash/scripts/reset_userpass
new file mode 100755
index 000000000..d34b629bf
--- /dev/null
+++ b/rescue/Flash/scripts/reset_userpass
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ modprobe unionfs > /dev/null 2>&1
+ modprobe squashfs > /dev/null 2>&1
+ modprobe loop > /dev/null 2>&1
+
+ mkdir -p $rootdir
+ mkdir -p $tmpdir/squash
+ mkdir -p $tmpdir/user
+ mkdir -p $tmpdir/union
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ mount -t squashfs -o loop $sfs_loop $tmpdir/squash > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting distrib.sqfs"
+ return 1
+ fi
+
+ mount -t ext2 -o loop $sys_loop $tmpdir/user > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting system.loop"
+ return 1
+ fi
+
+ mount -t unionfs -o dirs=$tmpdir/user=rw:$tmpdir/squash=ro \
+ none $tmpdir/union > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error creating union of distrib.sqfs and system.loop"
+ return 1
+ fi
+
+ chroot $tmpdir/union /etc/init.d/keytable start &> /dev/null
+ chroot $tmpdir/union /usr/bin/unicode_start
+
+ return 0
+}
+
+function doit() {
+
+ username=$(tail -1 $tmpdir/union/etc/passwd | cut -d ':' -f1)
+
+ clear
+ echo
+ echo -n "What is your username? [$username] "
+ read name
+
+ if [ -z "$name" ]; then
+ name="$username"
+ fi
+
+ echo
+ echo
+ chroot $tmpdir/union passwd $name
+ echo
+ echo
+
+ return 0
+}
+
+function cleanup() {
+
+ chroot $tmpdir/union /usr/bin/unicode_stop
+
+ umount $tmpdir/union > /dev/null 2>&1
+ umount $tmpdir/user > /dev/null 2>&1
+ umount $tmpdir/squash > /dev/null 2>&1
+ umount $rootdir > /dev/null 2>&1
+
+ rmdir $tmpdir/union $tmpdir/user $tmpdir/squash 2> /dev/null
+ rmdir $rootdir $tmpdir 2> /dev/null
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ sys_loop="$rootdir/loopbacks/system.loop"
+ sfs_loop="$rootdir/loopbacks/distrib.sqfs"
+else
+ sys_loop="$rootdir/.loopbacks/system.loop"
+ sfs_loop="$rootdir/.loopbacks/distrib.sqfs"
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
+exit 0
diff --git a/rescue/Flash/scripts/restore_systemloop b/rescue/Flash/scripts/restore_systemloop
new file mode 100755
index 000000000..39c56e030
--- /dev/null
+++ b/rescue/Flash/scripts/restore_systemloop
@@ -0,0 +1,167 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ mkdir -p $rootdir
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ if [ x"$version" = x"1.0" ]; then
+ mkdir -p $tmpdir/shared
+ if ! mount_sharedroot $tmpdir/shared; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function doit() {
+
+ if [ ! -d $dir ]; then
+ echo
+ echo "Can't find a backup directory in the Share partition"
+ echo
+ return 0
+ fi
+
+ cd $dir
+ i=1
+ for file in $(ls -c1 backup-*.bz2 2> /dev/null | sort -r | head -10); do
+ files[$i]="$file"
+ let i++
+ done
+ cd - > /dev/null
+
+ if [ $i -eq 1 ]; then
+ echo
+ echo 'No backup files found!'
+ echo
+ return 0
+ fi
+
+ while [ true ]; do
+
+ clear
+ echo
+ echo "The following backup files were found:"
+ echo
+
+ i=1
+ while [ -n "${files[$i]}" ]; do
+ echo "[$i] ${files[$i]}"
+ let i++
+ done
+ let i--
+ echo
+ echo '[0] Cancel / Return to main menu'
+
+ echo
+ echo 'Select from the list above, the file that you want to restore.'
+ echo 'The most recent files come first in the list.'
+ echo
+ echo -n "What backup file do you want to restore? [1] "
+ read option
+
+ if [ -z "$option" ]; then
+ option=1
+ fi
+ if [ x"$option" = x"0" ]; then
+ return 0
+ fi
+
+ if [ ! -f $dir/${files[$option]} ]; then
+ echo
+ echo "Error reading backup file ${files[$option]}!"
+ echo
+ echo -n 'Do you want to restore another backup file? [N/y] '
+ read confirm
+
+ if [ x"$confirm" = x"y" -o x"$confirm" = x"Y" ]; then
+ continue
+ else
+ return 0
+ fi
+ else
+
+ echo
+ echo -n 'Restoring backup file. This can take some time: '
+
+ bunzip2 -c $dir/${files[$option]} > $loop \
+ 2> /tmp/rescue-backup.err &
+
+ sleep 2
+
+ while ps | grep -q bunzip2; do
+ progress
+ done
+
+ sync
+ echo
+ echo
+
+ errsize=$(ls -la /tmp/rescue-backup.err | cut -d' ' -f5)
+ if [ $errsize -ne 0 ]; then
+ echo 'Error restoring user files!'
+ echo
+ return 1
+ else
+ echo 'Backup file restored!'
+ echo
+ break
+ fi
+ fi
+ done
+
+ return 0
+}
+
+function cleanup() {
+
+ if [ x"$version" = x"1.0" ]; then
+ umount $tmpdir/shared > /dev/null 2>&1
+ rmdir $tmpdir/shared 2> /dev/null
+ fi
+
+ umount $rootdir > /dev/null 2>&1
+ rmdir $rootdir $tmpdir 2> /dev/null
+
+ return 0
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ dir="$tmpdir/shared/backup"
+ loop="$rootdir/loopbacks/system.loop"
+else
+ dir="$rootdir/backup"
+ loop="$rootdir/.loopbacks/system.loop"
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
+exit 0
diff --git a/rescue/Flash/scripts/test_badblocks b/rescue/Flash/scripts/test_badblocks
new file mode 100755
index 000000000..3fb1f34d8
--- /dev/null
+++ b/rescue/Flash/scripts/test_badblocks
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+function prepare() {
+
+ return 0
+}
+
+function doit() {
+
+ clear
+ echo
+ echo "WARNING!"
+ echo
+ echo "Searching for bad blocks in Mandriva Flash is a slow process."
+ echo
+ echo -n "Do you want to continue? [N/y] "
+ read confirm
+
+ echo
+ echo
+
+ device=$(cat /tmp/rescue-device)
+
+ if [ x"$confirm" = x"y" -o x"$confirm" = x"Y" ]; then
+
+ /sbin/badblocks -n -v -s ${device}1
+ if [ x"$version" = x"1.0" ]; then
+ /sbin/badblocks -n -v -s ${device}2
+ fi
+ fi
+
+ echo
+ echo 'Bad blocks scan completed!'
+ echo
+
+ return 0
+}
+
+function cleanup() {
+
+ umount $rootdir > /dev/null 2>&1
+ rmdir $rootdir $tmpdir 2> /dev/null
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
diff --git a/rescue/Flash/scripts/upgrade b/rescue/Flash/scripts/upgrade
new file mode 100755
index 000000000..a81263c38
--- /dev/null
+++ b/rescue/Flash/scripts/upgrade
@@ -0,0 +1,196 @@
+#!/bin/bash
+
+# import functions library
+source rescue_common
+
+tmpdir="/tmp/flash-rescue-root"
+rootdir="$tmpdir/pen"
+
+
+config_files_network_scripts="etc/sysconfig/network-scripts/ifcfg-* \
+ etc/sysconfig/network-scripts/cellular.d \
+ etc/sysconfig/network-scripts/vpn.d \
+ etc/sysconfig/network-scripts/wireless.d"
+
+config_files_users="etc/passwd etc/shadow etc/group etc/gshadow"
+config_files_time="etc/localtime etc/ntp etc/ntp.conf"
+config_files="etc/sysconfig/* $config_files_users $config_files_time \
+ etc/wpa_supplicant.conf etc/shorewall etc/kde \
+ etc/udev/rules.d/61-*_config.rules"
+
+config_files_to_remove="etc/sysconfig/harddrake2"
+
+function prepare() {
+
+ modprobe unionfs > /dev/null 2>&1
+ modprobe squashfs > /dev/null 2>&1
+ modprobe loop > /dev/null 2>&1
+
+ mkdir -p $rootdir
+ mkdir -p $tmpdir/squash
+ mkdir -p $tmpdir/user
+ mkdir -p $tmpdir/union
+
+ if ! mount_usbroot $rootdir; then
+ return 1
+ fi
+
+ mount -t ext2 -o loop $sys_loop $tmpdir/user > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting system.loop"
+ return 1
+ fi
+
+ return 0
+}
+
+function get_existing_rpms() {
+
+ mount -t squashfs -o loop $sfs_loop $tmpdir/squash > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting distrib.sqfs"
+ return 1
+ fi
+
+ mount -t unionfs -o dirs=$tmpdir/user=rw:$tmpdir/squash=ro \
+ none $tmpdir/union
+ if [ $? -ne 0 ]; then
+ echo "Error creating union of distrib.sqfs and system.loop"
+ return 1
+ fi
+
+ chroot $tmpdir/squash rpm -qa | sort > /tmp/previous_rpms.list
+ if [ $? -ne 0 ]; then
+ echo "Error getting list of vanilla rpms installed on previous key"
+ fi
+
+ chroot $tmpdir/union rpm -qa | sort > /tmp/existing_rpms.list
+ if [ $? -ne 0 ]; then
+ echo "Error getting list of rpms installed prior to upgrade"
+ fi
+
+ umount $tmpdir/union > /dev/null 2>&1
+ umount $tmpdir/squash > /dev/null 2>&1
+
+ mkdir -p $tmpdir/user/root
+ diff /tmp/previous_rpms.list /tmp/existing_rpms.list | sed -n 's/^> //p' > $tmpdir/user/root/new_existing_rpms.list
+
+ return 0
+}
+
+function move_files() {
+ for i in $*; do
+ if [ -e $i ]; then
+ dir=`dirname $i`
+ [ "$dir" = "." ] || mkdir -p ..keep/$dir
+ mv $i ..keep/$dir || { echo "Error moving $i"; return 1; }
+ fi
+ done
+
+ return 0
+}
+
+function remove_non_user_nor_config_files() {
+
+ cd $tmpdir/user
+
+ rm -rf $config_files_to_remove
+
+ if [ -e ..keep ]; then
+ mv ..keep ..keep.bak
+ fi
+ if [ -e ..keep ]; then
+ echo "remove_non_user_nor_config_files can't work with existing temp dir"
+ return 1
+ fi
+
+ mkdir ..keep
+
+ move_files $config_files_network_scripts || return 1
+ rm -rf etc/sysconfig/network-scripts
+
+ move_files home root $config_files || return 1
+ rm -rf *
+ rm -rf .[^.]*
+
+ mv ..keep/* .
+ rmdir ..keep
+
+ cd - > /dev/null
+
+ return 0
+}
+
+function copy_new_version() {
+
+ return 0
+}
+
+function merge_config_files() {
+
+ mount -t squashfs -o loop $sfs_loop $tmpdir/squash > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Error mounting distrib.sqfs"
+ return 1
+ fi
+
+ ./upgrade.merge-users $tmpdir/user/etc $tmpdir/squash/etc
+
+ return 0
+}
+
+function doit() {
+
+ if [ -d $tmpdir/user/var/lib/rpm/Packages ]; then
+ get_existing_rpms || return 1
+ fi
+
+ remove_non_user_nor_config_files || return 1
+
+ copy_new_version
+
+ merge_config_files || return 1
+
+ return 0
+}
+
+function cleanup() {
+ cd /
+
+ umount $tmpdir/union > /dev/null 2>&1
+ umount $tmpdir/user > /dev/null 2>&1
+ umount $tmpdir/squash > /dev/null 2>&1
+ umount $rootdir > /dev/null 2>&1
+
+ rmdir $tmpdir/union $tmpdir/user $tmpdir/squash 2> /dev/null
+ rmdir $rootdir $tmpdir 2> /dev/null
+}
+
+clear
+trap cleanup SIGINT
+
+version=""
+if ! insert_pendrive; then
+ exit 1
+fi
+
+if [ x"$version" = x"1.0" ]; then
+ sys_loop="$rootdir/loopbacks/system.loop"
+ sfs_loop="$rootdir/loopbacks/distrib.sqfs"
+else
+ sys_loop="$rootdir/.loopbacks/system.loop"
+ sfs_loop="$rootdir/.loopbacks/distrib.sqfs"
+fi
+
+if ! prepare; then
+ cleanup
+ exit 1
+fi
+
+if ! doit; then
+ cleanup
+ exit 1
+fi
+
+cleanup
+exit 0
diff --git a/rescue/Flash/scripts/upgrade.merge-users b/rescue/Flash/scripts/upgrade.merge-users
new file mode 100755
index 000000000..297960e91
--- /dev/null
+++ b/rescue/Flash/scripts/upgrade.merge-users
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+
+use MDK::Common;
+
+@ARGV == 2 or die "merge_users <existing files dir> <new files dir>\n";
+
+my ($existing_dir, $new_dir) = @ARGV;
+
+merge('passwd', 'shadow');
+merge('group', 'gshadow');
+
+sub merge {
+ my ($main, $shadow) = @_;
+
+ my @new = cat_("$new_dir/$main");
+ my %new_ids = map { (split ':')[2] => $_ } @new;
+
+ my %names_to_have;
+ foreach (cat_("$existing_dir/$main")) {
+ my @l = split ':';
+ next if $l[0] eq 'nobody' || $l[2] < 500;
+ if (my $e = $new_ids{$l[2]}) {
+ $_ eq $e or warn "ERROR: conflicting entries:\n $_ $e";
+ } else {
+ push @new, $_;
+ $names_to_have{$l[0]} = 1;
+ }
+ }
+
+ my @new_shadow = grep { !/^root:/ } cat_("$new_dir/$shadow");
+ foreach (cat_("$existing_dir/$shadow")) {
+ my ($name) = split ':';
+ if ($name eq 'root') {
+ unshift @new_shadow, $_;
+ } elsif ($names_to_have{$name}) {
+ push @new_shadow, $_;
+ }
+ }
+
+ if (rename "$existing_dir/$main", "$existing_dir/$main.old") {
+ output("$existing_dir/$main", @new);
+ } else {
+ warn "rename $existing_dir/$main failed: $?\n";
+ <STDIN>;
+ }
+ if (rename "$existing_dir/$shadow", "$existing_dir/$shadow.old") {
+ output("$existing_dir/$shadow", @new_shadow);
+ } else {
+ warn "rename $existing_dir/$shadow failed: $?\n";
+ <STDIN>;
+ }
+}