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 \