From b97e5fb309e21f5305ad1f3e9aa7a8ccfb0c191c285d9b3aaa69720e9a8ce1a7 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Sep 2012 05:41:58 +0000 Subject: [PATCH] - add local patches to copy symlinks with mkinitrd (bnc#778149) OBS-URL: https://build.opensuse.org/package/show/Virtualization/libguestfs?expand=0&rev=116 --- libguestfs.changes | 5 + libguestfs.mkinitrd.1110.patch | 164 ++++++++++++++++++++++++ libguestfs.mkinitrd.1210.patch | 184 +++++++++++++++++++++++++++ libguestfs.mkinitrd.1220.patch | 219 +++++++++++++++++++++++++++++++++ libguestfs.spec | 30 ++++- 5 files changed, 601 insertions(+), 1 deletion(-) create mode 100644 libguestfs.mkinitrd.1110.patch create mode 100644 libguestfs.mkinitrd.1210.patch create mode 100644 libguestfs.mkinitrd.1220.patch diff --git a/libguestfs.changes b/libguestfs.changes index 6b15411..cfaa9ae 100644 --- a/libguestfs.changes +++ b/libguestfs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Sep 28 07:37:17 CEST 2012 - ohering@suse.de + +- add local patches to copy symlinks with mkinitrd (bnc#778149) + ------------------------------------------------------------------- Tue Sep 25 16:41:28 CEST 2012 - ohering@suse.de diff --git a/libguestfs.mkinitrd.1110.patch b/libguestfs.mkinitrd.1110.patch new file mode 100644 index 0000000..1620313 --- /dev/null +++ b/libguestfs.mkinitrd.1110.patch @@ -0,0 +1,164 @@ +--- + mkinitrd/scripts/setup-prepare.sh | 90 +++++++++++++++++++++++++++++++------- + mkinitrd/scripts/setup-progs.sh | 5 -- + 2 files changed, 77 insertions(+), 18 deletions(-) + +Index: 1110/mkinitrd/scripts/setup-prepare.sh +=================================================================== +--- 1110.orig/mkinitrd/scripts/setup-prepare.sh ++++ 1110/mkinitrd/scripts/setup-prepare.sh +@@ -13,43 +13,103 @@ + #%param_v: "Verbose mode." + #%param_L: "Disable logging." + #%param_h: "This help screen." + # + ###### Additional options + ## + ## Script inclusion may be overriden by + ## 1) creating a monster-initrd + ## 2) including the wanted module in the configuration option ADDITIONAL_FEATURES in /etc/sysconfig/initrd + ## 3) definition using the -f command line switch + ## + + # Install a binary file ++# cp_bin file target_filename ++# cp_bin file target_directory ++# cp_bin file file target_directory ++# file is either a regular file or a symlink. symlinks and all paths they point to will be copied ++# the "root" of target is $tmp_mnt, which is required to copy symlinks properly + cp_bin() { +- cp -a "$@" \ +- || exit_code=1 ++ local -a files ++ local target ++ local target_dirname ++ local file + +- # Remember the binaries installed. We need the list for checking +- # for dynamic libraries. +- while [ $# -gt 1 ]; do +- initrd_bins[${#initrd_bins[@]}]=$1 +- shift +- done +- # file may print '^setuid ELF ...' +- # suid mount will fail if mkinitrd was called as user +- if [ -L "$1" ]; then +- : do nothing with symlinks +- elif [ -d "$1" -o -f "$1" ]; then +- find "$1" -type f -print0 | xargs -0 chmod 0755 +- fi ++ # need at least two parameters, source and destination ++ if test $# -lt 2 ++ then ++ return 0 ++ fi ++ # store source filenames ++ until test $# -eq 1 ++ do ++ files=( ${files[@]} $1 ) ++ shift ++ done ++ # store target, either file or directory ++ target=$1 ++ # if more than two parameters, last entry must be a directory ++ if test ${#files[@]} -gt 1 ++ then ++ if ! test -d ${target} ++ then ++ return 0 ++ fi ++ target_dirname=${target} ++ else ++ # simplify symlink resolving for sinlge filename ++ target_dirname=${target%/*} ++ fi ++ ++ for file in ${files[@]} ++ do ++ local src dst ++ src=${file} ++ dst=${target} ++ # copy requested soure file as is to requested destination ++ cp -a -v --remove-destination ${src} ${dst} ++ # copy symlinks recursivly ++ while [ 1 ] ++ do ++ local tmp_src ++ if test -L ${src} ++ then ++ tmp_src=$(readlink ${src}) ++ if test "${tmp_src:0:1}" = "/" ++ then ++ src=${tmp_src} ++ else ++ # relative symlink ++ src=${src%/*}/${tmp_src} ++ fi ++ cp -a -v --remove-destination --parents ${src} $tmp_mnt ++ # if link target exists, proceed to next symlink target ++ if test -e "${src}" ++ then ++ continue ++ fi ++ fi ++ # exit loop in case of dead symlink or if target of symlink was reached ++ break ++ done ++ # if source file exists, add it to list of binaries ++ if test -e "${src}" ++ then ++ # file may print '^setuid ELF ...' ++ # suid mount will fail if mkinitrd was called as user ++ chmod -v 0755 $tmp_mnt/${src} ++ initrd_bins[${#initrd_bins[@]}]=${src} ++ fi ++ done + } + + # check if we should use script or feature $1 + use_script() { + local condition feature script file + + # always use when creating monster initrd + [ "$create_monster_initrd" ] && return 0 + + # Normalize to feature name + feature="${1##*/}" + feature="${feature#*-}" + feature="${feature%.sh}" +Index: 1110/mkinitrd/scripts/setup-progs.sh +=================================================================== +--- 1110.orig/mkinitrd/scripts/setup-progs.sh ++++ 1110/mkinitrd/scripts/setup-progs.sh +@@ -28,29 +28,28 @@ for script in $INITRD_PATH/boot/*.sh; do + echo "[ \"\$debug\" ] && echo running $file + source boot/$file + [ \"\$modules\" ] && load_modules" >> run_all.sh + [ "$condition" ] && echo "fi" >> run_all.sh + # and all programs it needs + for files in $(cat $script | grep '%programs: ' | sed 's/^#%programs: \(.*\)$/\1/'); do + for file in $(eval echo $files); do + if [ "${file:0:17}" = "/lib/mkinitrd/bin" ]; then + SOURCE=$file + DEST="./bin/" + elif [ "${file:0:1}" = "/" ]; then # absolute path files have to stay alive + SOURCE=$file + [ ! -e $file -a -e /usr$file ] && SOURCE="/usr$file" +- DEST=".$file" ++ DEST=".$SOURCE" + else +- SOURCE=$(which "$file") +- DEST="./bin/" ++ DEST=".$SOURCE" + fi + cp_bin "$SOURCE" "$DEST" + done + done + fi + done + + echo -ne "Features: " + echo $features + + [ -e "bin/sh" ] || ln -s /bin/bash bin/sh + diff --git a/libguestfs.mkinitrd.1210.patch b/libguestfs.mkinitrd.1210.patch new file mode 100644 index 0000000..76ff774 --- /dev/null +++ b/libguestfs.mkinitrd.1210.patch @@ -0,0 +1,184 @@ +--- + mkinitrd/scripts/setup-prepare.sh | 90 +++++++++++++++++++++++++++++++------- + mkinitrd/scripts/setup-progs.sh | 17 +------ + 2 files changed, 78 insertions(+), 29 deletions(-) + +Index: 1210/mkinitrd/scripts/setup-prepare.sh +=================================================================== +--- 1210.orig/mkinitrd/scripts/setup-prepare.sh ++++ 1210/mkinitrd/scripts/setup-prepare.sh +@@ -13,43 +13,103 @@ + #%param_R: "Print release (version)." + #%param_L: "Disable logging." + #%param_h: "This help screen." + # + ###### Additional options + ## + ## Script inclusion may be overriden by + ## 1) creating a monster-initrd + ## 2) including the wanted module in the configuration option ADDITIONAL_FEATURES in /etc/sysconfig/initrd + ## 3) definition using the -f command line switch + ## + + # Install a binary file ++# cp_bin file target_filename ++# cp_bin file target_directory ++# cp_bin file file target_directory ++# file is either a regular file or a symlink. symlinks and all paths they point to will be copied ++# the "root" of target is $tmp_mnt, which is required to copy symlinks properly + cp_bin() { +- cp -a "$@" \ +- || exit_code=1 ++ local -a files ++ local target ++ local target_dirname ++ local file + +- # Remember the binaries installed. We need the list for checking +- # for dynamic libraries. +- while [ $# -gt 1 ]; do +- initrd_bins[${#initrd_bins[@]}]=$1 +- shift +- done +- # file may print '^setuid ELF ...' +- # suid mount will fail if mkinitrd was called as user +- if [ -L "$1" ]; then +- : do nothing with symlinks +- elif [ -d "$1" -o -f "$1" ]; then +- find "$1" -type f -print0 | xargs -0 chmod 0755 +- fi ++ # need at least two parameters, source and destination ++ if test $# -lt 2 ++ then ++ return 0 ++ fi ++ # store source filenames ++ until test $# -eq 1 ++ do ++ files=( ${files[@]} $1 ) ++ shift ++ done ++ # store target, either file or directory ++ target=$1 ++ # if more than two parameters, last entry must be a directory ++ if test ${#files[@]} -gt 1 ++ then ++ if ! test -d ${target} ++ then ++ return 0 ++ fi ++ target_dirname=${target} ++ else ++ # simplify symlink resolving for sinlge filename ++ target_dirname=${target%/*} ++ fi ++ ++ for file in ${files[@]} ++ do ++ local src dst ++ src=${file} ++ dst=${target} ++ # copy requested soure file as is to requested destination ++ cp -a -v --remove-destination ${src} ${dst} ++ # copy symlinks recursivly ++ while [ 1 ] ++ do ++ local tmp_src ++ if test -L ${src} ++ then ++ tmp_src=$(readlink ${src}) ++ if test "${tmp_src:0:1}" = "/" ++ then ++ src=${tmp_src} ++ else ++ # relative symlink ++ src=${src%/*}/${tmp_src} ++ fi ++ cp -a -v --remove-destination --parents ${src} $tmp_mnt ++ # if link target exists, proceed to next symlink target ++ if test -e "${src}" ++ then ++ continue ++ fi ++ fi ++ # exit loop in case of dead symlink or if target of symlink was reached ++ break ++ done ++ # if source file exists, add it to list of binaries ++ if test -e "${src}" ++ then ++ # file may print '^setuid ELF ...' ++ # suid mount will fail if mkinitrd was called as user ++ chmod -v 0755 $tmp_mnt/${src} ++ initrd_bins[${#initrd_bins[@]}]=${src} ++ fi ++ done + } + + # check if we should use script or feature $1 + use_script() { + local condition feature script file + + # always use when creating monster initrd + [ "$create_monster_initrd" ] && return 0 + + # Normalize to feature name + feature="${1##*/}" + feature="${feature#*-}" + feature="${feature%.sh}" +Index: 1210/mkinitrd/scripts/setup-progs.sh +=================================================================== +--- 1210.orig/mkinitrd/scripts/setup-progs.sh ++++ 1210/mkinitrd/scripts/setup-progs.sh +@@ -24,48 +24,37 @@ for script in $INITRD_PATH/boot/*.sh; do + condition="$(sed -rn 's/^#[[:blank:]]*%if:[[:blank:]]*(.*)$/if [ \1 ]; then/p' < "$script")" + echo "$condition" >> run_all.sh + # -- remember dependent modules + sed -rn 's/^#[[:blank:]]*%modules:[[:blank:]]*(.*)$/modules="\1"/p' < $script >> run_all.sh + echo "[ \"\$debug\" ] && echo running $file + source boot/$file + [ \"\$modules\" ] && load_modules" >> run_all.sh + [ "$condition" ] && echo "fi" >> run_all.sh + # and all programs it needs + for files in $(sed -rn 's/^#[[:blank:]]*%programs:[[:blank:]]*(.*)$/\1/p' < "$script"); do + for file in $(eval echo $files); do + if [ "${file:0:17}" = "/lib/mkinitrd/bin" ]; then + SOURCE=$file +- DEST="./bin/" ++ DEST="${tmp_mnt}/bin/" + elif [ "${file:0:1}" = "/" ]; then # absolute path files have to stay alive + SOURCE=$file + [ ! -e $file -a -e /usr$file ] && SOURCE="/usr$file" +- DEST=".$file" ++ DEST="${tmp_mnt}$SOURCE" + else + case "$(type -t "$file")" in + builtin) continue + esac + SOURCE=$(type -p "$file") +- DEST="./bin/" ++ DEST="${tmp_mnt}$SOURCE" + fi + + cp_bin "$SOURCE" "$DEST" +- +- # if we're given a symlink, always copy the linked file too +- if [ -L "$SOURCE" ]; then +- LINK=$(readlink -e "$SOURCE") +- if [ -e "$LINK" ]; then +- mkdir -p .$(dirname "$LINK") +- cp_bin "$LINK" ."$LINK" +- else +- echo 2>&1 "WARNING: $LINK is a dangling symlink" +- fi +- fi + done + done + fi + done + + echo -ne "Features: " + echo $features + + [ -e "bin/sh" ] || ln -s /bin/bash bin/sh + diff --git a/libguestfs.mkinitrd.1220.patch b/libguestfs.mkinitrd.1220.patch new file mode 100644 index 0000000..18fb8c3 --- /dev/null +++ b/libguestfs.mkinitrd.1220.patch @@ -0,0 +1,219 @@ +--- + mkinitrd/scripts/setup-prepare.sh | 126 ++++++++++++++++++++++---------------- + mkinitrd/scripts/setup-progs.sh | 17 ----- + 2 files changed, 79 insertions(+), 64 deletions(-) + +Index: 1220/mkinitrd/scripts/setup-prepare.sh +=================================================================== +--- 1220.orig/mkinitrd/scripts/setup-prepare.sh ++++ 1220/mkinitrd/scripts/setup-prepare.sh +@@ -13,77 +13,103 @@ + #%param_R: "Print release (version)." + #%param_L: "Disable logging." + #%param_h: "This help screen." + # + ###### Additional options + ## + ## Script inclusion may be overriden by + ## 1) creating a monster-initrd + ## 2) including the wanted module in the configuration option ADDITIONAL_FEATURES in /etc/sysconfig/initrd + ## 3) definition using the -f command line switch + ## + + # Install a binary file +-cp_link() { +- # Copy the target of the given link $1 to the destination $2 +- # spaces and special characters in file names will break things +- if [ -h "$1" ]; then +- lnkTarget=$(readlink $1) +- if [ -e $lnkTarget ];then +- cp -a $lnkTarget $2/$lnkTarget +- else +- # This link points to something in the same directory +- lnkSrc="$1" +- # Get the base bath of the link origin +- lnkSrcBase=${lnkSrc%/*} +- cp -a $lnkSrcBase/$lnkTarget $2/$lnkSrcBase/$lnkTarget +- fi +- return 1 +- fi +- return 0 +-} +- ++# cp_bin file target_filename ++# cp_bin file target_directory ++# cp_bin file file target_directory ++# file is either a regular file or a symlink. symlinks and all paths they point to will be copied ++# the "root" of target is $tmp_mnt, which is required to copy symlinks properly + cp_bin() { +- cp -a "$@" \ +- || exit_code=1 +- +- if [ -h "$1" ]; then +- lnkTarget=$1 +- # Determine the base bath of the target +- targetPath="$2" +- targetBase=${targetPath%$1*} +- while [ 1 ]; do +- cp_link $lnkTarget $targetBase +- lnkCopied=$? +- if [ $lnkCopied = 0 ]; then +- if [ -e $lnkTarget ]; then +- initrd_bins[${#initrd_bins[@]}]=$lnkTarget +- fi +- break +- fi +- done +- else +- # Remember the binaries installed. We need the list for checking +- # for dynamic libraries. +- while [ $# -gt 1 ]; do +- initrd_bins[${#initrd_bins[@]}]=$1 +- shift +- done +- # file may print '^setuid ELF ...' +- # suid mount will fail if mkinitrd was called as user +- if [ -d "$1" -o -f "$1" ]; then +- find "$1" -type f -print0 | xargs -0 chmod 0755 +- fi +- fi ++ local -a files ++ local target ++ local target_dirname ++ local file ++ ++ # need at least two parameters, source and destination ++ if test $# -lt 2 ++ then ++ return 0 ++ fi ++ # store source filenames ++ until test $# -eq 1 ++ do ++ files=( ${files[@]} $1 ) ++ shift ++ done ++ # store target, either file or directory ++ target=$1 ++ # if more than two parameters, last entry must be a directory ++ if test ${#files[@]} -gt 1 ++ then ++ if ! test -d ${target} ++ then ++ return 0 ++ fi ++ target_dirname=${target} ++ else ++ # simplify symlink resolving for sinlge filename ++ target_dirname=${target%/*} ++ fi ++ ++ for file in ${files[@]} ++ do ++ local src dst ++ src=${file} ++ dst=${target} ++ # copy requested soure file as is to requested destination ++ cp -a -v --remove-destination ${src} ${dst} ++ # copy symlinks recursivly ++ while [ 1 ] ++ do ++ local tmp_src ++ if test -L ${src} ++ then ++ tmp_src=$(readlink ${src}) ++ if test "${tmp_src:0:1}" = "/" ++ then ++ src=${tmp_src} ++ else ++ # relative symlink ++ src=${src%/*}/${tmp_src} ++ fi ++ cp -a -v --remove-destination --parents ${src} $tmp_mnt ++ # if link target exists, proceed to next symlink target ++ if test -e "${src}" ++ then ++ continue ++ fi ++ fi ++ # exit loop in case of dead symlink or if target of symlink was reached ++ break ++ done ++ # if source file exists, add it to list of binaries ++ if test -e "${src}" ++ then ++ # file may print '^setuid ELF ...' ++ # suid mount will fail if mkinitrd was called as user ++ chmod -v 0755 $tmp_mnt/${src} ++ initrd_bins[${#initrd_bins[@]}]=${src} ++ fi ++ done + } + + # check if we should use script or feature $1 + use_script() { + local condition feature script file + + # always use when creating monster initrd + [ "$create_monster_initrd" ] && return 0 + + # Normalize to feature name + feature="${1##*/}" + feature="${feature#*-}" + feature="${feature%.sh}" +Index: 1220/mkinitrd/scripts/setup-progs.sh +=================================================================== +--- 1220.orig/mkinitrd/scripts/setup-progs.sh ++++ 1220/mkinitrd/scripts/setup-progs.sh +@@ -24,48 +24,37 @@ for script in $INITRD_PATH/boot/*.sh; do + condition="$(sed -rn 's/^#[[:blank:]]*%if:[[:blank:]]*(.*)$/if [ \1 ]; then/p' < "$script")" + echo "$condition" >> run_all.sh + # -- remember dependent modules + sed -rn 's/^#[[:blank:]]*%modules:[[:blank:]]*(.*)$/modules="\1"/p' < $script >> run_all.sh + echo "[ \"\$debug\" ] && echo running $file + source boot/$file + [ \"\$modules\" ] && load_modules" >> run_all.sh + [ "$condition" ] && echo "fi" >> run_all.sh + # and all programs it needs + for files in $(sed -rn 's/^#[[:blank:]]*%programs:[[:blank:]]*(.*)$/\1/p' < "$script"); do + for file in $(eval echo $files); do + if [ "${file:0:17}" = "/lib/mkinitrd/bin" ]; then + SOURCE=$file +- DEST="./bin/" ++ DEST="${tmp_mnt}/bin/" + elif [ "${file:0:1}" = "/" ]; then # absolute path files have to stay alive + SOURCE=$file + [ ! -e $file -a -e /usr$file ] && SOURCE="/usr$file" +- DEST=".$file" ++ DEST="${tmp_mnt}$SOURCE" + else + case "$(type -t "$file")" in + builtin) continue + esac + SOURCE=$(type -p "$file") +- DEST="./bin/" ++ DEST="${tmp_mnt}$SOURCE" + fi + + cp_bin "$SOURCE" "$DEST" +- +- # if we're given a symlink, always copy the linked file too +- if [ -L "$SOURCE" ]; then +- LINK=$(readlink -e "$SOURCE") +- if [ -e "$LINK" ]; then +- mkdir -p .$(dirname "$LINK") +- cp_bin "$LINK" ."$LINK" +- else +- echo 2>&1 "WARNING: $LINK is a dangling symlink" +- fi +- fi + done + done + fi + done + + echo -ne "Features: " + echo $features + + [ -e "bin/sh" ] || ln -s /bin/bash bin/sh + diff --git a/libguestfs.spec b/libguestfs.spec index 786d8ff..d9f7410 100644 --- a/libguestfs.spec +++ b/libguestfs.spec @@ -74,6 +74,9 @@ Patch1000: 1000-force-virtio_blk-in-old-guest-kernel.patch Source0: %{name}-%{version}.tar.gz Source10: libguestfs.mkinitrd.boot.sh Source11: libguestfs.mkinitrd.setup.sh +Source1220: libguestfs.mkinitrd.1220.patch +Source1210: libguestfs.mkinitrd.1210.patch +Source1110: libguestfs.mkinitrd.1110.patch Requires: guestfs-tools %description @@ -481,6 +484,29 @@ a \ ' mkinitrd/scripts/boot-guestfs.sh diff -u mkinitrd/scripts/boot-guestfs.sh~ mkinitrd/scripts/boot-guestfs.sh || : # +patched= +for p in \ + %{S:1220} \ + %{S:1210} \ + %{S:1110} \ +%if 0 + %{S:1140} \ +%endif + ; +do + if patch --dry-run -p1 < $p + then + patch -p1 < $p + patched=$p + break + elif patch --dry-run -R -p1 < $p + then + patched=$p + break + fi +done +test -n "$patched" + /sbin/mkinitrd_setup \ -s $PWD/mkinitrd/scripts \ -i $PWD/mkinitrd @@ -492,6 +518,7 @@ arch=i686 #? %endif cp -avL /boot/vmlinuz mkinitrd/boot_tmp/vmlinuz.${arch} cp -avL /boot/System.map-${kver} mkinitrd/boot_tmp +%if 0 # [Bug 778149] mkinitrd does not copy links correctly mkdir mkinitrd/bin_tmp for cmd in ` awk '/^#%%programs:/ { print $2 }' mkinitrd/scripts/boot-guestfs.sh | sort -u ` @@ -499,10 +526,11 @@ do cp -v ` PATH=${RPM_BUILD_ROOT}/usr/bin:${RPM_BUILD_ROOT}/usr/sbin:${PATH}:/sbin:/usr/sbin type -p $cmd ` mkinitrd/bin_tmp/ || : done chmod -v 755 mkinitrd/bin_tmp/* +%endif # additional_modules=" " -env PATH=$PWD/mkinitrd/bin_tmp:${PATH} \ +env PATH=${RPM_BUILD_ROOT}/usr/bin:${RPM_BUILD_ROOT}/usr/sbin:${PATH} \ bash -x \ /sbin/mkinitrd \ -l $PWD/mkinitrd \