From ae8b82e395c9530a66288f7a9e939242137d3f56 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 26 Jan 2012 11:33:51 +0100 Subject: [PATCH] add usrmove module --- dracut.spec | 1 + modules.d/30usrmove/do-usrmove.sh | 7 ++ modules.d/30usrmove/module-setup.sh | 19 ++++ modules.d/30usrmove/usrmove-convert.sh | 153 ++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 0 deletions(-) create mode 100755 modules.d/30usrmove/do-usrmove.sh create mode 100755 modules.d/30usrmove/module-setup.sh create mode 100755 modules.d/30usrmove/usrmove-convert.sh diff --git a/dracut.spec b/dracut.spec index 16c8aa3..06533e3 100644 --- a/dracut.spec +++ b/dracut.spec @@ -226,6 +226,7 @@ rm -rf $RPM_BUILD_ROOT %{dracutlibdir}/modules.d/05busybox %{dracutlibdir}/modules.d/10i18n %{dracutlibdir}/modules.d/10rpmversion +%{dracutlibdir}/modules.d/30usrmove %{dracutlibdir}/modules.d/50plymouth %{dracutlibdir}/modules.d/90btrfs %{dracutlibdir}/modules.d/90crypt diff --git a/modules.d/30usrmove/do-usrmove.sh b/modules.d/30usrmove/do-usrmove.sh new file mode 100755 index 0000000..8bdf5ab --- /dev/null +++ b/modules.d/30usrmove/do-usrmove.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +if getargbool 0 rd.usrmove; then + usrmove-convert "$NEWROOT" 2>&1 | vinfo +fi diff --git a/modules.d/30usrmove/module-setup.sh b/modules.d/30usrmove/module-setup.sh new file mode 100755 index 0000000..05b2366 --- /dev/null +++ b/modules.d/30usrmove/module-setup.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + [[ $mount_needs ]] && return 1 + return 255 +} + +depends() { + return 0 +} + +install() { + dracut_install bash + inst_hook pre-pivot 99 "$moddir/do-usrmove.sh" + inst "$moddir/usrmove-convert.sh" /usr/bin/usrmove-convert +} + diff --git a/modules.d/30usrmove/usrmove-convert.sh b/modules.d/30usrmove/usrmove-convert.sh new file mode 100755 index 0000000..3295074 --- /dev/null +++ b/modules.d/30usrmove/usrmove-convert.sh @@ -0,0 +1,153 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +set -x + +ROOT="$1" + +if [[ ! -d "$ROOT" ]]; then + echo "Usage: $0 " + exit 1 +fi + +if [[ "$ROOT" -ef / ]]; then + echo "Can't convert the running system." + echo "Please boot with 'usrmove' on the kernel command line," + echo "to update with the help of the initramfs," + echo "or run this script from a rescue system." + exit 1 +fi + +while [[ "$ROOT" != "${ROOT%/}" ]]; do + ROOT=${ROOT%/} +done + +needconvert() { + for dir in "$ROOT/bin" "$ROOT/sbin" "$ROOT/lib" "$ROOT/lib64"; do + if [[ -e "$dir" ]]; then + [[ -L "$dir" ]] || return 0 + fi + done + return 1 +} + +if ! needconvert; then + echo "Your system is already converted." + exit 0 +fi + +testfile="$ROOT/.usrmovecheck$$" +rm -f "$testfile" +> "$testfile" +if [[ ! -e "$testfile" ]]; then + echo "Cannot write to $ROOT/" + exit 1 +fi +rm -f "$testfile" + +testfile="$ROOT/usr/.usrmovecheck$$" +rm -f "$testfile" +> "$testfile" +if [[ ! -e "$testfile" ]]; then + echo "Cannot write to $ROOT/usr/" + exit 1 +fi +rm -f "$testfile" + +ismounted() { + while read a m a; do + [[ "$m" = "$1" ]] && return 0 + done < /proc/mounts + return 1 +} + +# clean up after ourselves no matter how we die. +cleanup() { + echo "Something failed. Move back to the original state" + for dir in "$ROOT/bin" "$ROOT/sbin" "$ROOT/lib" "$ROOT/lib64" \ + "$ROOT/usr/bin" "$ROOT/usr/sbin" "$ROOT/usr/lib" \ + "$ROOT/usr/lib64"; do + [[ -d "${dir}.usrmove-new" ]] && rm -fr "${dir}.usrmove-new" + if [[ -d "${dir}.usrmove-old" ]]; then + mv "$dir" "${dir}.del~" + mv "${dir}.usrmove-old" "$dir" + rm -fr "${dir}.del~" + fi + done +} + +trap 'ret=$?; [[ $ret -ne 0 ]] && cleanup;exit $ret;' EXIT +trap 'exit 1;' SIGINT + +ismounted "$ROOT/usr" || CP_HARDLINK="-l" + +set -e + +# merge / and /usr in new dir in /usr +for dir in bin sbin lib lib64; do + rm -rf "$ROOT/usr/${dir}.usrmove-new" + [[ -L "$ROOT/$dir" ]] && continue + [[ -d "$ROOT/$dir" ]] || continue + echo "Make a copy of \`$ROOT/usr/$dir'." + [[ -d "$ROOT/usr/$dir" ]] \ + && cp -ax $CP_HARDLINK "$ROOT/usr/$dir" "$ROOT/usr/${dir}.usrmove-new" + echo "Merge the copy with \`$ROOT/$dir'." + [[ -d "$ROOT/usr/${dir}.usrmove-new" ]] \ + || mkdir -p "$ROOT/usr/${dir}.usrmove-new" + cp -axT $CP_HARDLINK --backup --suffix=.usrmove~ "$ROOT/$dir" "$ROOT/usr/${dir}.usrmove-new" + echo "Clean up duplicates in \`$ROOT/usr/$dir'." + # delete all symlinks that have been backed up + find "$ROOT/usr/${dir}.usrmove-new" -type l -name '*.usrmove~' -delete || : + # replace symlink with backed up binary + find "$ROOT/usr/${dir}.usrmove-new" \ + -name '*.usrmove~' \ + -type f \ + -exec bash -c 'p="{}";o=${p%%%%.usrmove~}; + [[ -L "$o" ]] && mv -f "$p" "$o"' ';' || : +done +# switch over merged dirs in /usr +for dir in bin sbin lib lib64; do + [[ -d "$ROOT/usr/${dir}.usrmove-new" ]] || continue + echo "Switch to new \`$ROOT/usr/$dir'." + rm -fr "$ROOT/usr/${dir}.usrmove-old" + mv "$ROOT/usr/$dir" "$ROOT/usr/${dir}.usrmove-old" + mv "$ROOT/usr/${dir}.usrmove-new" "$ROOT/usr/$dir" +done + +# replace dirs in / with links to /usr +for dir in bin sbin lib lib64; do + [[ -L "$ROOT/$dir" ]] && continue + [[ -d "$ROOT/$dir" ]] || continue + echo "Create \`$ROOT/$dir' symlink." + rm -rf "$ROOT/${dir}.usrmove-old" || : + mv "$ROOT/$dir" "$ROOT/${dir}.usrmove-old" + ln -sfn usr/$dir "$ROOT/$dir" +done + +echo "Clean up backup files." +# everything seems to work; cleanup +for dir in bin sbin lib lib64; do + # if we get killed in the middle of "rm -rf", ensure not to leave + # an incomplete directory, which is moved back by cleanup() + [[ -d "$ROOT/usr/${dir}.usrmove-old" ]] \ + && mv "$ROOT/usr/${dir}.usrmove-old" "$ROOT/usr/${dir}.usrmove-old~" + [[ -d "$ROOT/${dir}.usrmove-old" ]] \ + && mv "$ROOT/${dir}.usrmove-old" "$ROOT/${dir}.usrmove-old~" +done + +for dir in bin sbin lib lib64; do + [[ -d "$ROOT/usr/${dir}.usrmove-old~" ]] \ + && rm -rf "$ROOT/usr/${dir}.usrmove-old~" || : + [[ -d "$ROOT/${dir}.usrmove-old~" ]] \ + && rm -rf "$ROOT/${dir}.usrmove-old~" || : +done + +set +e + +echo "Run ldconfig." +ldconfig -r "$ROOT" +echo "Set autorelabel flag." +> "$ROOT/.autorelabel" +echo "Done." +exit 0