Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skip patching absolute symlinks during finalize stage (related to issue 1338) #2055

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
108 changes: 65 additions & 43 deletions usr/share/rear/finalize/GNU/Linux/250_migrate_disk_devices_layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pushd $TARGET_FS_ROOT >&2

# Save the original restored files because in general any user data is sacrosanct,
# cf. how BACKUP_RESTORE_MOVE_AWAY is implemented in restore/default/990_move_away_restored_files.sh
save_original_file_dir="$VAR_DIR/saved_original_files/"
local save_original_file_dir="$VAR_DIR/saved_original_files/"
# Strip leading '/' to get a relative path that is needed inside the recovery system:
save_original_file_dir="${save_original_file_dir#/}"
# Create the save_original_file_dir with mode 0700 (rwx------)
Expand All @@ -27,52 +27,74 @@ save_original_file_dir="${save_original_file_dir#/}"
mkdir -p -m 0700 $save_original_file_dir
LogPrint "The original restored files get saved in $save_original_file_dir (in $TARGET_FS_ROOT)"

# The funny [] around the first letter make sure that shopt -s nullglob removes this file from the list if it does not exist.
# Files without a [] are mandatory, like fstab:
for file in [b]oot/{grub.conf,menu.lst,device.map} [e]tc/grub.* [b]oot/grub/{grub.conf,menu.lst,device.map} \
[b]oot/grub2/{grub.conf,grub.cfg,menu.lst,device.map} \
[e]tc/sysconfig/grub [e]tc/sysconfig/bootloader \
[e]tc/lilo.conf \
[e]tc/yaboot.conf \
[e]tc/mtab [e]tc/fstab \
[e]tc/mtools.conf \
[e]tc/smartd.conf [e]tc/sysconfig/smartmontools \
[e]tc/sysconfig/rawdevices \
[e]tc/security/pam_mount.conf.xml [b]oot/efi/*/*/grub.cfg
do
# Skip directory or file not found:
test -f "$file" || continue
# sed -i bails on symlinks, so we follow the symlink and patch the result
# absolute links are rebased on $TARGET_FS_ROOT (/etc/fstab => $TARGET_FS_ROOT/etc/fstab)
# on dead links we warn and skip them
if test -L "$file" ; then
linkdest="$( readlink -m "$file" | sed -e "s#^/#$TARGET_FS_ROOT/#" )"
if test -f "$linkdest" ; then
LogPrint "Using symlink '$file' destination '$linkdest'"
file="$linkdest"
else
LogPrint "Skipping dead symlink '$file'"
local symlink_target=""
local restored_file=""
# the funny [] around the first letter make sure that shopt -s nullglob removes this file from the list if it does not exist
# the files without a [] are mandatory, like fstab FIXME: but below there is [e]tc/fstab not etc/fstab - why?

for restored_file in [b]oot/{grub.conf,menu.lst,device.map} [e]tc/grub.* [b]oot/grub/{grub.conf,menu.lst,device.map} \
[b]oot/grub2/{grub.conf,grub.cfg,menu.lst,device.map} \
[e]tc/sysconfig/grub [e]tc/sysconfig/bootloader \
[e]tc/lilo.conf \
[e]tc/yaboot.conf \
[e]tc/mtab [e]tc/fstab \
[e]tc/mtools.conf \
[e]tc/smartd.conf [e]tc/sysconfig/smartmontools \
[e]tc/sysconfig/rawdevices \
[e]tc/security/pam_mount.conf.xml [b]oot/efi/*/*/grub.cfg
do
# Silently skip directories and file not found:
test -f "$restored_file" || continue
# 'sed -i' bails out on symlinks, so we follow the symlink and patch the symlink target
# on dead links we inform the user and skip them
# TODO: We should do this inside 'chroot $TARGET_FS_ROOT' so that absolute symlinks will work correctly
# cf. https://github.com/rear/rear/issues/1338
if test -L "$restored_file" ; then
if symlink_target="$( readlink -f "$restored_file" )" ; then
# symlink_target is an absolute path in the recovery system
# e.g. the symlink target of etc/mtab is /mnt/local/proc/12345/mounts
# because we use only 'pushd $TARGET_FS_ROOT' but not 'chroot $TARGET_FS_ROOT'.
# If the symlink target does not start with /mnt/local/ (i.e. if it does not start with $TARGET_FS_ROOT)
# it is an absolute symlink (e.g. inside $TARGET_FS_ROOT a symlink points to /absolute/path/file)
# and the target of an absolute symlink is not within the recreated system but in the recovery system
# where it does not make sense to patch files, cf. https://github.com/rear/rear/issues/1338
# so that we skip patching symlink targets that are not within the recreated system:
if ! echo $symlink_target | grep -q "^$TARGET_FS_ROOT/" ; then
LogPrint "Skip patching symlink $restored_file target $symlink_target not within $TARGET_FS_ROOT"
continue
fi
fi
# Skip empty files:
test -s "$file" || continue
# Save the original file:
# Clean up already existing stuff in save_original_file_dir
# that would be (partially) overwritten by the current copy
# (such stuff is considered as outdated leftover e.g. from a previous recovery)
# but keep already existing stuff in the save_original_file_dir because
# any user data is sacrosanct (also outdated stuff from a previous recovery):
rm -rf "$save_original_file_dir/$file"
# Copy the original file with its directory path:
cp -a --parents "$file" $save_original_file_dir
# Inform the user but do not error out here at this late state of "rear recover"
# when it failed to apply the layout mappings to one particular restored file:
if apply_layout_mappings "$file" ; then
LogPrint "Applied disk layout mappings to restored '$file' (in $TARGET_FS_ROOT)"
# If the symlink target contains /proc/ /sys/ /dev/ or /run/ we skip it because then
# the symlink target is considered to not be a restored file that needs to be patched
# cf. https://github.com/rear/rear/pull/2047#issuecomment-464846777
if echo $symlink_target | egrep -q '/proc/|/sys/|/dev/|/run/' ; then
LogPrint "Skip patching symlink $restored_file target $symlink_target on /proc/ /sys/ /dev/ or /run/"
continue
fi
LogPrint "Patching symlink $restored_file target $symlink_target"
restored_file="$symlink_target"
else
LogPrintError "Failed to apply disk layout mappings to restored '$file' (in $TARGET_FS_ROOT)"
LogPrint "Skip patching dead symlink $restored_file"
continue
fi
fi
# Silently skip empty files:
test -s "$restored_file" || continue
# Save the original file:
# Clean up already existing stuff in save_original_file_dir
# that would be (partially) overwritten by the current copy
# (such stuff is considered as outdated leftover e.g. from a previous recovery)
# but keep already existing stuff in the save_original_file_dir because
# any user data is sacrosanct (also outdated stuff from a previous recovery):
rm -rf "$save_original_file_dir/$restored_file"
# Copy the original file with its directory path:
cp $v -a --parents "$restored_file" $save_original_file_dir
# Inform the user but do not error out here at this late state of "rear recover"
# when it failed to apply the layout mappings to one particular restored file:
if apply_layout_mappings "$restored_file" ; then
LogPrint "Applied disk layout mappings to restored '$restored_file' (in $TARGET_FS_ROOT)"
else
LogPrintError "Failed to apply disk layout mappings to restored '$restored_file' (in $TARGET_FS_ROOT)"
fi
done

popd >&2
Expand Down
80 changes: 50 additions & 30 deletions usr/share/rear/finalize/GNU/Linux/250_migrate_lun_wwid.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,68 @@
# skip if no mappings
test -s "$LUN_WWID_MAP" || return 0

# FIXME: What the heck does that "TAG-15-migrate-wwid" mean?
Log "TAG-15-migrate-wwid: $LUN_WWID_MAP"

# create the SED_SCRIPT
SED_SCRIPT=""
# create the sed script
local sed_script=""
local old_wwid new_wwid device
while read old_wwid new_wwid device ; do
SED_SCRIPT="$SED_SCRIPT;/${old_wwid}/s/${old_wwid}/${new_wwid}/g"
done < <(sort -u $LUN_WWID_MAP)

sed_script="$sed_script;/${old_wwid}/s/${old_wwid}/${new_wwid}/g"
done < <( sort -u $LUN_WWID_MAP )
# debug line:
Log "$SED_SCRIPT"
Debug "$sed_script"

# Careful in case of 'return' after 'pushd' (must call the matching 'popd' before 'return'):
pushd $TARGET_FS_ROOT >&2

# now run sed
LogPrint "Migrating LUN WWIDs in certain restored files in $TARGET_FS_ROOT to current WWIDs ..."

local symlink_target=""
local restored_file=""
# the funny [] around the first letter make sure that shopt -s nullglob removes this file from the list if it does not exist
# the files without a [] are mandatory, like fstab
for file in [e]tc/elilo.conf \
[e]tc/fstab
do

#[[ -d "$file" ]] && continue # skip directory
[[ ! -f "$file" ]] && continue # skip directory and file not found
# sed -i bails on symlinks, so we follow the symlink and patch the result
# on dead links we warn and skip them
# TODO: maybe we must put this into a chroot so that absolute symlinks will work correctly
if test -L "$file" ; then
if linkdest="$(readlink -f "$file")" ; then
# if link destination is residing on /proc we skip it silently
echo $linkdest | grep -q "^/proc" && continue
LogPrint "Patching '$linkdest' instead of '$file'"
file="$linkdest"
else
LogPrint "Not patching dead link '$file'"
continue
fi
# the files without a [] are mandatory, like fstab FIXME: but below there is [e]tc/fstab not etc/fstab - why?
for restored_file in [e]tc/elilo.conf \
[e]tc/fstab
do
# Silently skip directories and file not found:
test -f "$restored_file" || continue
# 'sed -i' bails out on symlinks, so we follow the symlink and patch the symlink target
# on dead links we inform the user and skip them
# TODO: We should do this inside 'chroot $TARGET_FS_ROOT' so that absolute symlinks will work correctly
# cf. https://github.com/rear/rear/issues/1338
if test -L "$restored_file" ; then
if symlink_target="$( readlink -f "$restored_file" )" ; then
# symlink_target is an absolute path in the recovery system
# e.g. the symlink target of etc/mtab is /mnt/local/proc/12345/mounts
# because we use only 'pushd $TARGET_FS_ROOT' but not 'chroot $TARGET_FS_ROOT'.
# If the symlink target does not start with /mnt/local/ (i.e. if it does not start with $TARGET_FS_ROOT)
# it is an absolute symlink (i.e. inside $TARGET_FS_ROOT a symlink points to /absolute/path/file)
# and the target of an absolute symlink is not within the recreated system but in the recovery system
# where it does not make sense to patch files, cf. https://github.com/rear/rear/issues/1338
# so that we skip patching symlink targets that are not within the recreated system:
if ! echo $symlink_target | grep -q "^$TARGET_FS_ROOT/" ; then
LogPrint "Skip patching symlink $restored_file target $symlink_target not within $TARGET_FS_ROOT"
continue
fi
# If the symlink target contains /proc/ /sys/ /dev/ or /run/ we skip it because then
# the symlink target is considered to not be a restored file that needs to be patched
# cf. https://github.com/rear/rear/pull/2047#issuecomment-464846777
if echo $symlink_target | egrep -q '/proc/|/sys/|/dev/|/run/' ; then
LogPrint "Skip patching symlink $restored_file target $symlink_target on /proc/ /sys/ /dev/ or /run/"
continue
fi
LogPrint "Patching symlink $restored_file target $symlink_target"
restored_file="$symlink_target"
else
LogPrint "Skip patching dead symlink $restored_file"
continue
fi

LogPrint "Patching file '$file'"
sed -i "$SED_SCRIPT" "$file"
StopIfError "Patching '$file' with sed failed."
fi
LogPrint "Patching LUN WWIDs in $restored_file to current WWIDs"
# Do not error out at this late state of "rear recover" (after the backup was restored) but inform the user:
sed -i "$sed_script" "$restored_file" || LogPrintError "Migrating LUN WWIDs in $restored_file to current WWIDs failed"
done

popd >&2
Expand Down
50 changes: 45 additions & 5 deletions usr/share/rear/finalize/GNU/Linux/260_rename_diskbyid.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# remove existing disk-by-id mappings
# FIXME: Don't we actually not 'remove' but 'replace' or 'migrate' disk-by-id mappings?
#
# We call sed once for each substituation
# it would be better to build one sed script and use this later
Expand Down Expand Up @@ -35,7 +36,7 @@ NEW_ID_FILE="$TMP_DIR/diskbyid_mappings"
# cf. https://github.com/rear/rear/issues/1845
# but hopefully the code below is sufficiently robust
# so that things work at least for those entries that are correct:
apply_layout_mappings "$OLD_ID_FILE" || LogPrintError "Failed to apply layout mappings to $OLD_ID_FILE (may cause failures during 'rename_diskbyid')"
apply_layout_mappings "$OLD_ID_FILE" || LogPrintError "Failed to apply layout mappings to $OLD_ID_FILE (may cause failures during 'rename_diskbyid')"

# replace the device names with the real devices

Expand Down Expand Up @@ -66,11 +67,49 @@ done < "$OLD_ID_FILE" > "$NEW_ID_FILE"

sed_change_monitor="$TMP_DIR/by-id_change"

LogPrint "Migrating disk-by-id mappings in certain restored files in $TARGET_FS_ROOT to current disk-by-id mappings ..."

local file=""
local realfile=""
local symlink_target=""
for file in $FILES; do
realfile="$TARGET_FS_ROOT/$file"
[ ! -f "$realfile" ] && continue # if file is not there continue with next one
# Silently skip directories and file not found:
test -f "$realfile" || continue
# 'sed -i' bails out on symlinks, so we follow the symlink and patch the symlink target
# on dead links we inform the user and skip them
# TODO: We should do this inside 'chroot $TARGET_FS_ROOT' so that absolute symlinks will work correctly
# cf. https://github.com/rear/rear/issues/1338
if test -L "$realfile" ; then
if symlink_target="$( readlink -f "$realfile" )" ; then
# symlink_target is an absolute path in the recovery system
# e.g. the symlink target of etc/mtab is /mnt/local/proc/12345/mounts
# because we use only 'pushd $TARGET_FS_ROOT' but not 'chroot $TARGET_FS_ROOT'.
# If the symlink target does not start with /mnt/local/ (i.e. if it does not start with $TARGET_FS_ROOT)
# it is an absolute symlink (e.g. inside $TARGET_FS_ROOT a symlink points to /absolute/path/file)
# and the target of an absolute symlink is not within the recreated system but in the recovery system
# where it does not make sense to patch files, cf. https://github.com/rear/rear/issues/1338
# so that we skip patching symlink targets that are not within the recreated system:
if ! echo $symlink_target | grep -q "^$TARGET_FS_ROOT/" ; then
LogPrint "Skip patching symlink $realfile target $symlink_target not within $TARGET_FS_ROOT"
continue
fi
# If the symlink target contains /proc/ /sys/ /dev/ or /run/ we skip it because then
# the symlink target is considered to not be a restored file that needs to be patched
# cf. https://github.com/rear/rear/pull/2047#issuecomment-464846777
if echo $symlink_target | egrep -q '/proc/|/sys/|/dev/|/run/' ; then
LogPrint "Skip patching symlink $realfile target $symlink_target on /proc/ /sys/ /dev/ or /run/"
continue
fi
LogPrint "Patching symlink $realfile target $symlink_target"
realfile="$symlink_target"
else
LogPrint "Skip patching dead symlink $realfile"
continue
fi
fi
# keep backup
cp "$realfile" "${realfile}.rearbak"
cp $v "$realfile" "${realfile}.rearbak"
# we should consider creating a sed script within a string
# and then call sed once (as done other times)
while read ID DEV_NAME ID_NEW; do
Expand Down Expand Up @@ -104,15 +143,16 @@ for file in $FILES; do
sed -i "s#$ID_FULL\$#/dev/$DEV_NAME#gw /dev/null" "$realfile" >> "$sed_change_monitor"
fi

# Checking if sed change something in a file (by using w sed flag)
# Checking if sed changed something in a file (by using w sed flag)
# LogPrint only when a change was made.
if test -s "$sed_change_monitor" ; then
LogPrint "Patching $file: Replacing [$ID_FULL] by [$ID_NEW_FULL]"
LogPrint "Replaced '$ID_FULL' by '$ID_NEW_FULL' in $realfile"
rm "$sed_change_monitor"
fi

done < $NEW_ID_FILE
done

# TODO: Use 'local' variables for that:
unset ID DEV_NAME ID_NEW SYMLINKS ID_FULL ID_NEW_FULL

9 changes: 9 additions & 0 deletions usr/share/rear/finalize/GNU/Linux/280_migrate_uuid_tags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ do
# symlink_target is an absolute path in the recovery system
# e.g. the symlink target of etc/mtab is /mnt/local/proc/12345/mounts
# because we use only 'pushd $TARGET_FS_ROOT' but not 'chroot $TARGET_FS_ROOT'.
# If the symlink target does not start with /mnt/local/ (i.e. if it does not start with $TARGET_FS_ROOT)
# it is an absolute symlink (i.e. inside $TARGET_FS_ROOT a symlink points to /absolute/path/file)
# and the target of an absolute symlink is not within the recreated system but in the recovery system
# where it does not make sense to patch files, cf. https://github.com/rear/rear/issues/1338
# so that we skip patching symlink targets that are not within the recreated system:
if ! echo $symlink_target | grep -q "^$TARGET_FS_ROOT/" ; then
LogPrint "Skip patching symlink $restored_file target $symlink_target not within $TARGET_FS_ROOT"
continue
fi
# If the symlink target contains /proc/ /sys/ /dev/ or /run/ we skip it because then
# the symlink target is considered to not be a restored file that needs to be patched
# cf. https://github.com/rear/rear/pull/2047#issuecomment-464846777
Expand Down